Using ADO.NET Data Service
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.
本文会通过一个具体的例子来演示如何使用ADO.NET Data Service以及其部分特性。
- 选择数据源
ADO.NET Data Service是由两部分组成的,一部分是其运行时,它提供了诸如Addressing(即URI Translation), Open Format for Data Representation(公开的数据表现形式-JSON/ATOM), 数据传输协议等。另一部分就是数据访问部分,这部分是可以选择的,LINQ或者Entity Framework都是可以的,Data Service本身的功能就是将这些数据源暴露成一个面向web的数据服务。
创建一个服务分为两步:
- 用ADO.NET Entity Framework来创建一个Entity Data Model – 这是为了以EDM来展现你的数据架构
- 建立数据服务
- 配置用户对数据访问的权限
如何创建一个EDM我们在这里不想多讲,下边的图和简单步骤会告诉你如何来创建一个EDM。
- 创建一个Web Application,这里我们命名为Allan.DataServiceDemo
- 在Solution Explore中右键点击选择添加新项,选择添加ADO.NET Entity Data Model,在Name中输入Northwind.edmx.
3.在Entity Data Model Wizard中设置ConnectionString.点击下一步.
4.在接下来的选择表、视图的窗体中选择你想要加入到EDM中的表。这里我们选择Employees, Territories和EmployeesTerrories表,然后点Finish. 到此我们的EDM已经完成了。接下来我们要做的事在EDM的基础上来构建Data Service.
- 创建数据服务
5. 右键点击项目并在弹出菜单中选择添加新项目。在弹出的对话框中选择 ADO.NET Data Service, 并将名称更名为NorthwindService.svc.通过这里你会发现,其实ADO.NET Data Service本质上是一个WCF.
6. Service本身已经建立,但现在还没有将数据暴露给客户端,并且没有相应的数据访问控制。当点击上一步中的Add按钮后,系统会打开NorthwindService.svc.cs文件,在这里我们需要做如下更改来暴露数据。
- 将数据访问层类设立为被暴露的服务的数据源
- 设定对相关数据实体集的权限和可访问性。
要做到这两点只需要更改一下所示的高两部分即可。第一个高两部分表示我们将NorthwindEntities作为我们的数据源。NorthwindEntities是我们刚才创建的EDMX的类名,Employees等表都已经作为其属性被Mapping成对象。第二个高亮部分是控制EntitySet(其实就是对应的表一级)的访问权限。例如你仍然可以通过下边的代码仅仅暴露Employees对象的只读权限:config.SetEntityAccessRule(“Employees”,EntitySetRights.AllRead.这样,服务只会暴露Employees集合并且只接受读取,而不能有更新操作。
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来验证你的工作是否正确。
- Addressing: Accessing Data Service via URIs
在前边提到过,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的标记、函数等,以供查询和参阅。
- Logical Operators – 逻辑运算符
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 |
- Arithmetic Operators – 算数运算符
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 |
- Functions – 函数
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来做一些简单的查询和过滤。通过分析查询结果你会清楚的看到:
- 当有多个对象被返回是,在atom模式下,数据以feed的方式返回。
- 每个entry包含一个对象。
- 每个entry会提供link标签来给出自己的URL和其关联对象的URL
- 属性会被包含在Content内部以application/xml表示
- 每个属性都是content内一个子节点。
- 所有的数据和关系均以纯XML表现
- 默认情况下关联对象不被加载(expand可以加载)
- Query Interceptors – 查询拦截
查询拦截非常有用,它起个代理或者把关的作用。当你仅仅想把具有某种状态或者特征的数据返回给客户端时,用拦截查询就可以实现。比如,数据库中的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 – 数据更新拦截
看起来,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 为我们提供了快速构建一个数据服务的平台,但到目前为止,除了数据库中的对象(还不包括存储过程),我们仍然无法加入自己的方法,这显得好像很不灵活。当然,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
Using ADO.NET Data Service的更多相关文章
- ADO.NET Data Service
关于ADO.NET Entity Framework部分的内容见ADO.NET Entity Framework(1-4) http://www.cnblogs.com/foundation/arch ...
- WCF Data Service 使用小结 (一)—— 了解OData协议
最近做了一个小项目,其中用到了 WCF Data Service,之前是叫 ADO.NET Data Service 的.关于WCF Data Service,博客园里的介绍并不多,但它确实是个很好的 ...
- WCF Data Service 使用小结 —— 了解OData(一)
最近做了一个小项目,其中用到了 WCF Data Service,之前是叫 ADO.NET Data Service 的.关于WCF Data Service,博客园里的介绍并不多,但它确实是个很好的 ...
- 一步一步学Silverlight 2系列(17):数据与通信之ADO.NET Data Services
概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...
- 我的WCF Data Service 系列 (一、为什么要有WCF Data Service)
开篇先说两名题外话, 在博问上,经常看到有个问性能问题,比如Entity Framework的性能行不行啊之类的. 其实这个行不行,关键还是看对象,一夜家族的老七可能勉强吃点蓝片片,也就行了,可真要让 ...
- 自定义Data Service Providers
自定义Data Service Providers 作者:AlexJ 翻译:谈少民 原文链接:http://blogs.msdn.com/b/alexj/archive/2010/01/07/data ...
- WCF Data Service
WCF Data Service:http://www.cnblogs.com/shanyou/category/240225.html
- WCF Data Service 使用小结(二) —— 使用WCF Data Service 创建OData服务
在 上一章 中,介绍了如何通过 OData 协议来访问 OData 服务提供的资源.下面来介绍如何创建一个 OData 服务.在这篇文章中,主要说明在.NET的环境下,如何使用 WCF Data Se ...
- 调用WCF Data Service的几点Tips
使用Linq实现sql in statement的时候,用EF的时候可以通过Contains.Exists的方法实现.但是在使用WCF Data Service的context的时候,会报不支持该方法 ...
随机推荐
- 使用中科大源下载android源码
我的系统时manjaro linux 最新版的,安装过了git和curl软件 一.如果没有安装的同学,请使用命令: pacman -S git curl 我这里安装了python3和python2,但 ...
- vmware tools安装过程
每次通过vmware安装Ubuntu的时候,总是会多多少少出点问题.好容易披荆斩棘把镜像安好了,然而屏幕却只有小小一个,不能显示大屏,我就知道肯定是缺少了vmware tools.于是点击左上方菜单中 ...
- 线程之间通信 等待(wait)和通知(notify)
线程通信概念: 线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程之间的通信就成为整体的必用方式之一.当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同 ...
- dhcp 学习整理
centos 6.5 rpm: dhcp-4.1.1-25.P1.el6.x86_64 dhcp-common-4.1.1-25.P1.el6.x86_64 服务: /etc/rc.d/init.d/ ...
- [Python Cookbook] Numpy Array Slicing and Indexing
1-D Array Indexing Use bracket notation [ ] to get the value at a specific index. Remember that inde ...
- 线程和进程(Java)
一.线程概述 线程是程序运行的基本执行单元.当操作系统(不包括单线程的操作系统,如微软早期的DOS)在执行一个程序时,会在系统中建立一个进程,而在这个进程中,必须至少建立一个线程(这个线程被称为主线程 ...
- 2016北京集训测试赛(十七)Problem B: 银河战舰
Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...
- Mysql乱码问题解决历程
可能是因为看了太多网上的关于这个问题的解决办法,可能当时是我自己没有看明白也或许是情况不一样,反正都没有解决我当初遇到的问题,现在想想可能是自己当初太无知了,第二个原因是原来大多数情况下是在windo ...
- js CacheQueue
(function(){ var CacheQueue=function(name,weightValue,maxLength,clearTimerTime){ //public this.name ...
- 2016.6.20 maven下载与安装步骤
(1)进入maven官网的下载页面. https://maven.apache.org/download.cgi (2)下载页面中可以看到很多可供下载的链接.gz和zip只是压缩方式的区别,这两个都是 ...