Steve Marx在这里写了关于在Azure表存储中执行更新的新扩展方法,作为新存储协议版本的一部分:
http://blog.smarx.com/posts/extension-methods-for-the-august-storage-features但是,如果我想执行原始的无条件合并或抛出操作,而不是进行反转操作,该怎么办?我想合并一个对象,更新一个字段,但如果实体不存在就抛出,而不是创建一个只包含我正在合并的属性的新实体。
这可能吗?注意,我想在其他地方使用upsert,所以我让IoC为我提供从GetDataServiceContext2011
而不是GetDataServiceContext
创建的上下文。我想我可以在两者之间交替,但当Azure团队更新官方库时,这将无济于事。
根据MSDN:
插入或合并实体操作使用Merge谓词,必须是使用2011-08-18或更新版本调用。此外,它没有使用If-Match头。这些属性区分了该操作Update Entity操作,但请求体是相同的
那么,我如何让存储库在保存时发出通配符If-Match
而不是根本不发出If-Match
?
只需使用AttachTo
和星号作为etag。这将导致If-Match: *
。下面是一个完整的工作示例:
class Entity : TableServiceEntity
{
public string Text { get; set; }
public Entity() { }
public Entity(string rowkey) : base(string.Empty, rowkey) { }
}
class Program
{
static void Update(CloudStorageAccount account)
{
var ctx = account.CreateCloudTableClient().GetDataServiceContext();
var entity = new Entity("foo") { Text = "bar" };
ctx.AttachTo("testtable", entity, "*");
ctx.UpdateObject(entity);
ctx.SaveChangesWithRetries();
}
static void Main(string[] args)
{
var account = CloudStorageAccount.Parse(args[0]);
var tables = account.CreateCloudTableClient();
tables.CreateTableIfNotExist("testtable");
var ctx = tables.GetDataServiceContext();
try { Update(account); } catch (Exception e) { Console.WriteLine("Exception (as expected): " + e.Message); }
ctx.AddObject("testtable", new Entity("foo") { Text = "foo" });
ctx.SaveChangesWithRetries();
try { Update(account); } catch (Exception e) { Console.WriteLine("Unexpected exception: " + e.Message); }
Console.WriteLine("Now text is: " + tables.GetDataServiceContext().CreateQuery<Entity>("testtable").Where(e => e.PartitionKey == string.Empty && e.RowKey == "foo").Single().Text);
tables.DeleteTableIfExist("testtable");
}
}