Deleting Entities from Windows Azure Without Querying First
The most obvious way of deleting an entity using the ADO.NET Data Services client library is to query first (via LINQ), and then call DeleteObject
to delete the entity, like this:
svc = new TestContext(); var item = (from i in svc.TestTable where i.PartitionKey == "item1pk" && i.RowKey == "item1rk" select i).Single(); svc.DeleteObject(item); svc.SaveChanges();
However, this means that a delete takes two roundtrips. In some cases, you may know the unique key (partition key plus row key) of an entity already, and you’d like to delete without first querying. There is a way to do this. You need to construct a dummy local entity with the right partition and row keys, and then AttachTo
this object, specifying an ETag
of “*”
(to prevent a conflict when your delete encounters the ETag
of the real entity). The code looks like this:
svc = new TestContext(); item = new TestEntity("item2pk", "item2rk"); svc.AttachTo("TestTable", item, "*"); svc.DeleteObject(item); svc.SaveChanges();
What do they look like over HTTP?
The first method (query-and-delete) looks like a GET
followed by a DELETE
. Note the If-Match
header in the DELETE
which specifies the ETag
returned during the GET
.
GET /TestTable(PartitionKey='item1pk',RowKey='item1rk') HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
x-ms-date: Sun, 30 Nov 2008 06:02:27 GMT
Authorization: SharedKeyLite smarxtest:yNeUvY5puNFfdMENJdHxRc1n5E/Qetlyyk9fIX/tVmM=
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Host: smarxtest.table.core.windows.net
HTTP/1.1 200 OK
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: application/atom+xml;charset=utf-8
ETag: W/"datetime'2008-11-30T06%3A02%3A53.1863478Z'"
Server: Table Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 24f43295-e6d5-45f6-abca-6da3b99fe758
Date: Sun, 30 Nov 2008 06:02:52 GMT
<…body omitted…>
DELETE /TestTable(PartitionKey='item1pk',RowKey='item1rk') HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
x-ms-date: Sun, 30 Nov 2008 06:02:27 GMT
Authorization: SharedKeyLite smarxtest:yNeUvY5puNFfdMENJdHxRc1n5E/Qetlyyk9fIX/tVmM=
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Content-Type: application/atom+xml
If-Match: W/"datetime'2008-11-30T06%3A02%3A53.1863478Z'"
Host: smarxtest.table.core.windows.net
Content-Length: 0
The second method (unconditional delete) looks like the above DELETE
, but this time with an If-Match
header that specifies the ETag
“*”
. This means that the delete will ignore the entity’s ETag
, instead of raising a conflict error.
DELETE /TestTable(PartitionKey='item2pk',RowKey='item2rk') HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
x-ms-date: Sun, 30 Nov 2008 06:02:27 GMT
Authorization: SharedKeyLite smarxtest:sVSZmoN/bWw8mD8ZJ58abYkSjVvenmPukbFmMjmv3uQ=
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Content-Type: application/atom+xml
If-Match: *
Host: smarxtest.table.core.windows.net
Content-Length: 0
Which method should you use?
This really depends on the application. The key difference is that the first method ensures that nothing changed between when you queried for the entity and when you deleted it. (This is based on the ETag
check.) This is useful if there’s a possibility that since you decided to delete the entity, something else has changed the entity (and you care about this conflict).
However, if your code is as simple as what I have above, and you’re not doing any checking of the item you pulled back from table storage, you may as well use the second method, which will unconditionally delete the entity no matter what has happened to it since. This has the added benefit of only requiring one round-trip to storage, rather than two.