Data Service - 6. DataServiceContext (1)

来源:互联网 发布:php网站搭建教程 编辑:程序博客网 时间:2024/05/12 16:26

DataServiceContext 是 ADO.NET Data Service Client Library 的核心类,它负责管理 "数据实体" 的状态和执行环境。

var context = new TestEntities(new Uri("http://localhost:2394/test.svc"));

context.SendingRequest += (s, e) =>
{
e.Request.Proxy = new WebProxy("127.0.0.1", 8888);
};

context.WritingEntity += (s, e) =>
{
Console.WriteLine("Writing: {0}", e.Entity);
};

context.ReadingEntity += (s, e) =>
{
Console.WriteLine("Reading: {0}", e.Entity);
};

var user = context.Execute<User>(new Uri("/Users?$top=1", UriKind.Relative)).First();
Console.WriteLine(user.Name);

context.AddToUsers(new User { Name = "user13", Age = 12 });
context.SaveChanges();


1. 基本操作

我们首先看看基本的实体操作。为了获得相应的 HTTP 信息,可以使用 NirSoft SocketSniff 监听 ASP.NET Development Server。

var context = new TestEntities(new Uri("http://localhost:2394/test.svc"));

var user = new User { Name = "user13", Age = 12 };
context.AddToUsers(user);
context.SaveChanges();

Console.WriteLine(user.Id);


从下面的捕获结果,我们可以看到使用 POST 的提交内容,同时 Data Service 会返回所创建的实体刷新信息,因此我们能输出创建后的 User.Id。

Receive: Return Code: 0x00000000
POST /test.svc/Users HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Content-Type: application/atom+xml
Host: localhost:2394
Content-Length: 674
Expect: 100-continue
Connection: Keep-Alive

Send: Return Code: 0x00000000
HTTP/1.1 100 Continue
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 27 Apr 2009 04:52:09 GMT
Content-Length: 0

Receive: Return Code: 0x00000000
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/.../dataservices"...>
<category scheme="http://.../dataservices/scheme" term="TestModel.User" />
<title />
<updated>2009-04-27T04:52:09.859375Z</updated>
<author>
<name />
</author>
<id />
<content type="application/xml">
<m:properties>
<d:Age m:type="Edm.Int32">12</d:Age>
<d:Id m:type="Edm.Int32">0</d:Id>
<d:Name>user13</d:Name>
</m:properties>
</content>
</entry>

Send: Return Code: 0x00000000
HTTP/1.1 201 Created
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 27 Apr 2009 04:52:09 GMT
X-AspNet-Version: 2.0.50727
DataServiceVersion: 1.0;
Location: http://localhost:2394/Test.svc/Users(35)
Cache-Control: no-cache
Content-Type: application/atom+xml;charset=utf-8
Content-Length: 1001
Connection: Close

Send: Return Code: 0x00000000
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://localhost:2394/Test.svc/" ...>
<id>http://localhost:2394/Test.svc/Users(35)</id>
<title type="text"></title>
<updated>2009-04-27T04:52:09Z</updated>
<author>
<name />
</author>
<link rel="edit" title="User" href="Users(35)" />
<link rel="..." type="application/atom+xml;type=feed" title="UserDetail" href="Users(35)/UserDetail" />
<category term="TestModel.User" scheme="http://schemas.microsoft.com.../dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">35</d:Id>
<d:Name>user13</d:Name>
<d:Age m:type="Edm.Int32">12</d:Age>
</m:properties>
</content>
</entry>


和 EF 不同,对于更新的实体,在 SaveChanges() 之前,我们必须调用 UpdateObject()。

var context = new TestEntities(new Uri("http://localhost:2394/test.svc"));

var user = context.Users.First();
Console.WriteLine(user.Age);

user.Age += 10;
context.UpdateObject(user);

context.SaveChanges();


实体被正确更新,不过 Data Service 并没有返回任何更新结果信息。

Receive: Return Code: 0x00000000
PUT /test.svc/Users(1) HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Content-Type: application/atom+xml
Host: localhost:2394
Content-Length: 714
Expect: 100-continue

Receive: Return Code: 0x00000000
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" ...>
<category scheme="http://.../dataservices/scheme" term="TestModel.User" />
<title />
<updated>2009-04-27T04:58:41.96875Z</updated>
<author>
<name />
</author>
<id>http://localhost:2394/Test.svc/Users(1)</id>
<content type="application/xml">
<m:properties>
<d:Age m:type="Edm.Int32">32</d:Age>
<d:Id m:type="Edm.Int32">1</d:Id>
<d:Name>user1</d:Name>
</m:properties>
</content>
</entry>

Send: Return Code: 0x00000000
HTTP/1.1 204 No Content
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 27 Apr 2009 04:58:42 GMT
X-AspNet-Version: 2.0.50727
DataServiceVersion: 1.0;
Cache-Control: no-cache
ETag:
Content-Length: 0
Connection: Close


删除操作和更新类似,需要调用 DeleteObject()。

var context = new TestEntities(new Uri("http://localhost:2394/test.svc"));

var user = context.Users.First();
context.DeleteObject(user);

context.SaveChanges();


Data Service 直接通过 HTTP Head 中的查询路径来执行删除操作。

Receive: Return Code: 0x00000000
DELETE /test.svc/Users(1) HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Content-Type: application/atom+xml
Host: localhost:2394
Content-Length: 0

Send: Return Code: 0x00000000
HTTP/1.1 204 No Content
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 27 Apr 2009 05:04:15 GMT
X-AspNet-Version: 2.0.50727
DataServiceVersion: 1.0;
Cache-Control: no-cache
Content-Length: 0
Connection: Close


当我们一次提交多个 "变更" 操作时,默认情况下 DataServiceContext 会执行多次 HTTP Request。

var context = new TestEntities(new Uri("http://localhost:2394/test.svc"));

var users = context.Users.Take(3);
foreach (var user in users)
{
context.DeleteObject(user);
}

context.AddToUsers(new User { Name = "userx", Age = 12 });
context.SaveChanges();


Request 1

Receive: Return Code: 0x00000000
DELETE /test.svc/Users(2) HTTP/1.1

...


Request 2

Receive: Return Code: 0x00000000
DELETE /test.svc/Users(3) HTTP/1.1

...


Request 3

Receive: Return Code: 0x00000000
DELETE /test.svc/Users(4) HTTP/1.1

...


Request 4

Receive: Return Code: 0x00000000
POST /test.svc/Users HTTP/1.1

...


很显然,这种方式效率低下。为此 SaveChanges() 提供了 SaveChangesOptions.Batch 参数,允许我们在一个 Request 中提交多个处理。

var context = new TestEntities(new Uri("http://localhost:2394/test.svc"));

var users = context.Users.Take(3);
foreach (var user in users)
{
context.DeleteObject(user);
}

context.AddToUsers(new User { Name = "userx", Age = 12 });
context.SaveChanges(SaveChangesOptions.Batch);


这次的 HTTP 内容比较复杂。

Receive: Return Code: 0x00000000
POST /test.svc/$batch HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 1.0;NetFx
Content-Type: multipart/mixed; boundary=batch_ff7c47f5-debc-4666-b28f-68fa2c20da8e
Host: localhost:2394
Content-Length: 1744
Expect: 100-continue

Send: Return Code: 0x00000000
HTTP/1.1 100 Continue
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 27 Apr 2009 05:11:54 GMT
Content-Length: 0

Receive: Return Code: 0x00000000
--batch_ff7c47f5-debc-4666-b28f-68fa2c20da8e
Content-Type: multipart/mixed; boundary=changeset_c3b8b770-31b6-4441-b643-3be12df9f173

--changeset_c3b8b770-31b6-4441-b643-3be12df9f173
Content-Type: application/http
Content-Transfer-Encoding: binary

DELETE http://localhost:2394/test.svc/Users(5) HTTP/1.1
Content-ID: 2

--changeset_c3b8b770-31b6-4441-b643-3be12df9f173
Content-Type: application/http
Content-Transfer-Encoding: binary

DELETE http://localhost:2394/test.svc/Users(6) HTTP/1.1
Content-ID: 4

--changeset_c3b8b770-31b6-4441-b643-3be12df9f173
Content-Type: application/http
Content-Transfer-Encoding: binary

DELETE http://localhost:2394/test.svc/Users(7) HTTP/1.1
Content-ID: 6

--changeset_c3b8b770-31b6-4441-b643-3be12df9f173
Content-Type: application/http
Content-Transfer-Encoding: binary

POST http://localhost:2394/test.svc/Users HTTP/1.1
Content-ID: 7
Content-Type: application/atom+xml;type=entry
Content-Length: 673

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" ...>
<category scheme="http://.../dataservices/scheme" term="TestModel.User" />
<title />
<updated>2009-04-27T05:11:54.0625Z</updated>
<author>
<name />
</author>
<id />
<content type="application/xml">
<m:properties>
<d:Age m:type="Edm.Int32">12</d:Age>
<d:Id m:type="Edm.Int32">0</d:Id>
<d:Name>userx</d:Name>
</m:properties>
</content>
</entry>
--changeset_c3b8b770-31b6-4441-b643-3be12df9f173--
--batch_ff7c47f5-debc-4666-b28f-68fa2c20da8e--

Send: Return Code: 0x00000000
HTTP/1.1 202 Accepted
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 27 Apr 2009 05:11:54 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: no-cache
Content-Type: multipart/mixed; boundary=batchresponse_16b4356c-2c3b-47fd-b8b6-6e325b62079b
Content-Length: 2249
Connection: Close

Send: Return Code: 0x00000000
--batchresponse_16b4356c-2c3b-47fd-b8b6-6e325b62079b
Content-Type: multipart/mixed; boundary=changesetresponse_ff28a2bf-5231-45ed-8581-e3a8a7637a47

--changesetresponse_ff28a2bf-5231-45ed-8581-e3a8a7637a47
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
Content-ID: 2
Cache-Control: no-cache
DataServiceVersion: 1.0;

--changesetresponse_ff28a2bf-5231-45ed-8581-e3a8a7637a47
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
Content-ID: 4
Cache-Control: no-cache
DataServiceVersion: 1.0;

--changesetresponse_ff28a2bf-5231-45ed-8581-e3a8a7637a47
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
Content-ID: 6
Cache-Control: no-cache
DataServiceVersion: 1.0;

--changesetresponse_ff28a2bf-5231-45ed-8581-e3a8a7637a47
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 201 Created
Content-ID: 7
Content-Type: application/atom+xml;charset=utf-8
Cache-Control: no-cache
Location: http://localhost:2394/Test.svc/Users(37)
DataServiceVersion: 1.0;

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<entry xml:base="http://localhost:2394/Test.svc/" ...>
<id>http://localhost:2394/Test.svc/Users(37)</id>
<title type="text"></title>
<updated>2009-04-27T05:11:54Z</updated>
<author>
<name />
</author>
<link rel="edit" title="User" href="Users(37)" />
<link rel="..." type="application/atom+xml;type=feed" title="UserDetail" href="Users(37)/UserDetail" />
<category term="TestModel.User" scheme="http://.../dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Id m:type="Edm.Int32">37</d:Id>
<d:Name>userx</d:Name>
<d:Age m:type="Edm.Int32">12</d:Age>
</m:properties>
</content>
</entry>
--changesetresponse_ff28a2bf-5231-45ed-8581-e3a8a7637a47--
--batchresponse_16b4356c-2c3b-47fd-b8b6-6e325b62079b--


对 Data Service Client Library 的用户而言,事情很简单,执行效率也相应提高。但是其他语言的用户可就遭罪了,得自己拼接大量的字符串,但愿 Data Service Team 以后能给出其他语言的调用库,而不仅仅是 for Microsoft Ajax。