ADO.NET Data Service是随同Visual Studio 2008 SP1提供的用于构建在数据对象模型 (如EF-DEMX, LINQ-DBML) 之时来快速提供企业网内外的轻量级数据服务。ADO.NET Data Service Framework的目标是提供一个天生与web相结合的灵活的数据服务。它其中最醒目的特色就是经过URIs来指向以特定方式(JSON/ATOM)展示的数据(块),并以REST方式来展示。所支持的URIs访问方式经过对标准HTTP verbs如GET, POST, PUT和DELETE的支持来完成对数据的CRUD.web
本文会经过一个具体的例子来演示如何使用ADO.NET Data Service以及其部分特性。数据库
ADO.NET Data Service是由两部分组成的,一部分是其运行时,它提供了诸如Addressing(即URI Translation), Open Format for Data Representation(公开的数据表现形式-JSON/ATOM), 数据传输协议等。另外一部分就是数据访问部分,这部分是能够选择的,LINQ或者Entity Framework都是能够的,Data Service自己的功能就是将这些数据源暴露成一个面向web的数据服务。服务器
建立一个服务分为两步:架构
如何建立一个EDM咱们在这里不想多讲,下边的图和简单步骤会告诉你如何来建立一个EDM。app
3.在Entity Data Model Wizard中设置ConnectionString.点击下一步.ide
4.在接下来的选择表、视图的窗体中选择你想要加入到EDM中的表。这里咱们选择Employees, Territories和EmployeesTerrories表,而后点Finish. 到此咱们的EDM已经完成了。接下来咱们要作的事在EDM的基础上来构建Data Service.函数
5. 右键点击项目并在弹出菜单中选择添加新项目。在弹出的对话框中选择 ADO.NET Data Service, 并将名称改名为NorthwindService.svc.经过这里你会发现,其实ADO.NET Data Service本质上是一个WCF.this
6. Service自己已经创建,但如今尚未将数据暴露给客户端,而且没有相应的数据访问控制。当点击上一步中的Add按钮后,系统会打开NorthwindService.svc.cs文件,在这里咱们须要作以下更改来暴露数据。atom
要作到这两点只须要更改一下所示的高两部分便可。第一个高两部分表示咱们将NorthwindEntities做为咱们的数据源。NorthwindEntities是咱们刚才建立的EDMX的类名,Employees等表都已经做为其属性被Mapping成对象。第二个高亮部分是控制EntitySet(其实就是对应的表一级)的访问权限。例如你仍然能够经过下边的代码仅仅暴露Employees对象的只读权限:config.SetEntityAccessRule(“Employees”,EntitySetRights.AllRead.这样,服务只会暴露Employees集合而且只接受读取,而不能有更新操做。spa
public class NorthwindService : DataService<NorthwindEntities> { // This method is called only once to initialize service-wide policies. public static void InitializeService(IDataServiceConfiguration config) { // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. // Examples: config.SetEntitySetAccessRule("*", EntitySetRights.All); // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); } } |
大功告成,你能够经过View In Browser来验证你的工做是否正确。
在前边提到过,Data Service经过URIs来指向a piece of data。也就是说咱们经过URL就能够来作到访问数据,而且具备必定的数据过滤功能。抛弃高级的查询选项不说,基本的URL就能够来访问EntitySet和Entity,以致于某个字段,字段的值等等。经过浏览你的Northwind.svc,咱们能够看到如下数:
这里暴露了Employees和Territories两个数据集,这和咱们以前设定的是相同的。经过如下的访问列表,你能够很容易的来在这个数据集合中导航,并获取你想要的数据。
Resource |
URI |
Service |
http://localhost:4588/NorthwindService.svc/ |
Entity Set |
http://localhost:4588/NorthwindService.svc/Employees |
Entity |
http://localhost:4588/NorthwindService.svc/Employees(1) |
Relationship |
http://localhost:4588/NorthwindService.svc/Employees(1)/Address |
Property |
http://localhost:4588/NorthwindService.svc/Employees(1)/Address/City |
Property |
http://localhost:4588/NorthwindService.svc/Employees(1)/FirstName |
ADO.NET Data Service一样提供了如下的查询选项:
Option |
Description |
Example |
expand |
相似于LINQ中的LoadOptions,以此来指定加载此对象相关的经过expand指定的对象。若是须要加载多个对象,用逗号分隔。 |
http://localhost:4588/NorthwindService.svc/Employees(1)?$expand=Territories 同事加载当前employee对应的Territories. |
|
指定排序方式。语法为:$orderby=Field [ASC|DESC], [Field[ASC|DESC]] |
http://localhost:4588/NorthwindService.svc/Employees?$orderby=FirstName |
Skip Top |
相似于LINQ中的Skip(PageSize * PageIndex).Take(PageSize)用来实现分页。表示越过多少条记录,取接下来开始的几条记录。也可分开始使用两个选项。 |
http://localhost:4588/NorthwindService.svc/Employees?$orderby=FirstName&$skip=3&$top=3 http://localhost:4588/NorthwindService.svc/Employees? $skip=3 |
Filter |
经过filter这个参数能够在URL里传递过滤条件。 |
对于如上边所示的查询表达式,ADO.NET Data Service提供了一些函数和标记来帮助咱们组建适合的查询表达式(Query Expression).下表总结了常见的组建Query Expression的标记、函数等,以供查询和参阅。
Operator |
Description |
Operator |
Description |
eq |
Equal |
ne |
Not Equal |
gt |
Greater than |
ge |
Greater than or equal |
lt |
Less than |
le |
Less than or equal |
and |
Logical and |
|
Logical or |
not |
Logical negation |
() |
Precedence grouping |
Operator |
Description |
Example |
add |
Addition |
/Product?filter=UnitPrice add 5 gt 10 |
sub |
Subtraction |
/Product?filter=UnitPrice sub 5 gt 10 |
mul |
Multiplication |
/Orders?$filter=Freight mul 800 gt 2000 |
div |
Division |
/Orders?$filter=Freight div 10 eq 4 |
mod |
Modulo |
/Orders?$filter=Freight mod 10 eq 0 |
String Functions |
|||
bool substringof(string p0, string p1) |
bool endswith(string p0, string p1) |
||
bool startswith(string p0, string p1) |
int length(string p0) |
||
int indexof(string arg) |
string insert(string p0,int pos, string p1) |
||
string remove(string p0, int pos) |
string remove(string p0, int pos, int length) |
||
string remove(string p0, string find, string replace) |
string substring(string p0, int pos) |
||
string substring(string p0, int pos, int length) |
string tolower(string p0) |
||
string toupper(string p0) |
string trim(string p0) |
||
string concat(string p0, string p1) |
|
||
Date Functions |
|||
int day(DateTime) |
int hour(DateTime) |
int minute(DateTime) |
|
int month(DateTime) |
int second(DateTime) |
int year(DateTime) |
|
Math Functions |
|||
double round(double) |
decimal round(decimal) |
double floor(double) |
|
decimal floor(decimal) |
double ceiling(double) |
decimal ceiling(decimal) |
|
经过这些看似简单的函数和逻辑/算数操做符,能够在很大程度上经过URL来作一些简单的查询和过滤。经过分析查询结果你会清楚的看到:
查询拦截很是有用,它起个代理或者把关的做用。当你仅仅想把具备某种状态或者特征的数据返回给客户端时,用拦截查询就能够实现。好比,数据库中的Employee信息,对于已经离开公司的员工咱们会将其状态设置为Leave,而在咱们不打算将这些信息流露出去时,写一个Query Interceptor仅仅返回状态<>Leave的记录,那么全部客户端请求与Employee有关的数据时将被强制只能获得状态不为Leave的记录。换句话说,Query Interceptor的代理函数返回的数据在表面上替换了Employees的记录。
下边的示例限定了客户端仅能获得国家是USA的Employees信息:
[QueryInterceptor("Employees")] public Expression<Func<Employees, bool>> ReturnUSAEmployees() { return e => e.Country == "USA"; } |
Query Interceptors是面向EntitySet(也就是Table)的,经过修改QueryInterceptorAttribute的参数,你能够给任何一个EntitySet来建立一个查询拦截器。看看咱们刚才设置的查询拦截器是否工做呢?
没错,仅仅返回了5条Country=USA的记录。Nice!
看起来,Change Interceptors和Query Interceptors很类似,都是用来拦截客户端操做的。不一样的是,前一个word,一个是面向query的,一个是面向change的。顾名思义,Change Interceptors面向的就是提交到服务器的的数据更新操做:包括Add, Change 和Delete,分别对应在数据添加操做,数据更改操做和数据删除操做—这些是由UpdateOperations参数来提供的。下边的示例实现了在执行添加操做时,若是Employee实例的Country属性为空,则默认设置为USA:
[ChangeInterceptor("Employees")] public void AssignDefaultCountry(Employees c, UpdateOperations operation) { if (operation == UpdateOperations.Add) { if (c.Country.Trim().Length == 0) { c.Country = "USA"; } } } |
不要忘记给这个方法加入ChangeInterceptor属性。而对于所拦截的操做对象,一样是经过更改ChangeInterceptorAttribute的参数来实现的。
ADO.NET Data Service 为咱们提供了快速构建一个数据服务的平台,但到目前为止,除了数据库中的对象(还不包括存储过程),咱们仍然没法加入本身的方法,这显得好像很不灵活。固然,ADO.NET Data Service仍是为咱们提供了这样的一种方式来扩展已有的整套生成好的数据服务的。你能够添加一些你本身的方法,例如操做存储过程,本身的逻辑,返回特殊处理后的数据这样的方法,而后经过添加WebGetAttribute来使其变成一个ServiceOperation来暴露给客户。
[WebGet] public IQueryable<Employees> GetEmployeesByCountry(string country) { var employees = from c in this.CurrentDataSource.Employees where c.Country == country select c;
return employees; } |
同时还要设置这个方法的权限(InitializeService方法中):
config.SetServiceOperationAccessRule("GetEmployeesByCountry", ServiceOperationRights.All); |
如何去访问这个方法呢?由于你没法再meta中(实际上就是http://localhost:4588/NorthwindService.svc)找到对这个方法的描述。很简单,直接试验一下下边的URL是否工做呢?
http://localhost:4588/NorthwindService.svc/GetEmployeesByCountry?Country='USA' |
服务端的设置好像该有的都有了哦?除了Data Service的表现方式:Atom仍是JSON,这个另行解决吧,起码得有传输的数据包来展示。另外的有关客户端消费的(服务端消费和客户端AJAX消费)咱们在下一个话题中来介绍吧:)
点击连接下载练习代码: http://files.cnblogs.com/zlgcool/Allan.DataServiceDemo.rar