Entity Framework4.0 (九EF4与WCF Data Service的结合使用(转)
前面我们讲述了EF4的数据绑定。知道EF4的容器可以作为数据源控件的数据源。 以前我们作数据绑定是指向Dataset,使用DataAdapter与数据库连接,然后fill到dataset中。当我们使用EF4的数据绑定时,我 们的数据源控件不再依靠DataAdapter直接与数据库交互,而是依靠EF4容器,然后再由EF4与数据库交互。
这一次我们讲述:EF4与WCF Data Servicer的结合使用:EF4容器作为Data Service的数据提供者。
如果你对WCF Data Service不了解,没关系。这和Web Service很相像。如果你对Web Service也不了解,也没关系。咱们先把程序跑起来,你看看有多简单就知道是咋回事了。(其实,好多人刚开始接触新事物的时候,一股脑儿找到的资料全是定义。任何一个物事都不是语言文字可以准备定义的。就算定义准确了,能保证读者也能理解准确吗?所以,最简单的方式就是演示出来,让大家看看。就OK了。如果想深入研究,也至少知道努力的方向了。这就是所谓的:"先主杆,后枝叶"的学习过程)呵呵。
好了,不再废话了,大家肯定都烦俺絮叨了。呵呵,
==================================================================
1.启动Visual Studio2010 :File-->new Project-->ASP.NET Web Application. 项目名称:EFWCFDemo。
2.删除项目中使用不到的文件夹和文件(防止它们在这里混淆视听):如下图:
3.在项目EFWCFDemo上面右键—》Add-->New Item .选择ADO.NET Entity Data Modell 名称:Northwind.如下图:
4.在项目EFWCFDemo上面右键—》AddàNew Item. 选择 WCF Data Service:名称:EFWCFService。如下图:
5. 添加完以后,会默认打开EFWCFService.svc.cs文件。如果没有打开,你可以双击EFWCFService.svc即可打开EFWCFService.svc.cs文件。有如下代码:
1 public class EFWCFService : DataService< /* TODO: put your data source class name here */ > 2 { 3 // This method is called only once to initialize service-wide policies. 4 public static void InitializeService(DataServiceConfiguration config) 5 { 6 // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. 7 // Examples: 8 // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead); 9 // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); 10 11 12 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; 13 } 14 }
更改成下面的代码:(我们就是指定了类EFWCFService的父类的泛型类型为NorthwindEntities。
NorthwindEntities其实就是EF4的容器类了,所以把容器当作泛型参数的实参传进去,Data Service就到该容器中取数据了。为了方便起见,我们把*.edmx和EFWCFService.svc文件放在了同一个项目的同一个 namespace下面。你也可以根据实际需要把它们分开。使用的时候,再把相应的namespace添加进去就行了。)
同时我们也在代码中添加了一行: config.SetEntitySetAccessRule("*",EntitySetRights.All); 这是配置对EF4容器中的EntitySet的访问权限。第一个参数:“*”代表全部。因为我们只有一个实体集CategorySet。所以一会在浏览器 中我们只会看到一个Categories。第二个参数:EntitySetRights.All指拥有全部的权限。EntitySetRights枚举值 比较简单:见名知意,所以不多讲了。
public class EFWCFService : DataService< NorthwindEntities > { // This method is called only once to initialize service-wide policies. public static void InitializeService(DataServiceConfiguration config) { // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. // Examples: // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead); // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All); config.SetEntitySetAccessRule("*",EntitySetRights.All); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; } }
浏览器显示如下:
1 <?xml version="1.0" encoding="utf-8" standalone="yes" ?> 2 - <service xml:base="http://localhost:1713/EFWCFService.svc/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app"> 3 - <workspace> 4 <atom:title>Default</atom:title> 5 - <collection href="Categories"> 6 <atom:title>Categories</atom:title> 7 </collection> 8 </workspace> 9 </service>
说明:第5行:href 的值为当前实体集相对于WCF Data Service项目的URi:即在http://localhost:1713/EFWCFService.svc/的后面再追加:Categories就是当前实体集的URi,你可以试下:如果有类似于“您正在查看的源包含频繁更新的内容。订阅源后,该源会添加到“常见源列表”中。该源的更新信息会自动下载到计算机,通过 Internet Explorer 及其他程序可以查看这些信息”的提示。你可以在浏览器上:工具-》internet选项-如下图:
然后,你再访问CategorySet的URi就ok了。
6.在解决方案上面:右键-》Add -》New Item 选择Windows Form Application。名称:EFWCFTest。
在EFWCFTest项目下面的的References节点上右键,然后添加web service如下图:
在窗体Form1上面添加两个按钮:一个Button(名称:btnFill。显示文本:Fill)和一个ListBox(名称:lboxCategory)如下图:
给btnFill添加Click事件:代码如下:
1 View Code 2 using System; 3 using System.Collections.Generic; 4 using System.ComponentModel; 5 using System.Data; 6 using System.Drawing; 7 using System.Linq; 8 using System.Text; 9 using System.Windows.Forms; 10 using EFWCFTest.EFWCFReference; 11 12 namespace EFWCFTest 13 { 14 public partial class Form1 : Form 15 { 16 public Form1() 17 { 18 InitializeComponent(); 19 } 20 21 private void btnFill_Click(object sender, EventArgs e) 22 { 23 NorthwindEntities svc = new NorthwindEntities(new Uri("http://localhost:1713/EFWCFService.svc/")); 24 foreach (Category c in svc.Categories) 25 { 26 this.lboxCategory.Items.Add(string.Format("{0}::{1}",c.CategoryID,c.CategoryName)); 27 } 28 } 29 } 30 }
注意:
代码第9行:添加了一个命名空间:该命名空间是由添加Web 引用的时候生成的,代表的是本地代理类的命名空间。我们是通过直接操作本地代理,然后由本地代理去查找、访问wcf data service所公开的方法的。
代码第22行,此时的NorthwindEntities已经不再是EF4中的NorthwindEntities了。因为我们在窗体项目中未引用 EF4,我们只是添加了一个Web 引用,指向了WCF Data Service的URi。由WCF Data Service去EF4中找到数据。那代码第22行,此时的NorthwindEntities来自哪呢?你可以在VS2010中定位到该类,然后发现: 它只是一个本地代理类。并不是EF4中,由*.edmx所映射成的类。只是碰巧它们的名字默认是一样的。(不要混淆了哟!!)
设置EFWCFTest为启动项目,然后运行程序。
点击Fill按钮。如下图:
如果你想像以前使用EF4容器那样使用LINQ 去查询代理时,也可以用以下代码实现:btnFill的click事件。(这里假设我们需要找到CategoryName以“B”开头的实体)
1 private void btnFill_Click(object sender, EventArgs e) 2 { 3 NorthwindEntities svc = new NorthwindEntities(new Uri("http://localhost:1713/EFWCFService.svc/")); 4 5 var categories = from c in svc.Categories 6 where c.CategoryName.StartsWith("B") 7 select new { c.CategoryID, c.CategoryName }; 8 9 foreach (var c in categories) 10 { 11 this.lboxCategory.Items.Add(string.Format("{0}::{1}", c.CategoryID, c.CategoryName)); 12 } 13 14 }
svc.Categories 的返回类型是:DataServiceQuery<T>,而LINQ表达式筛选后得到的接口是IQueryable<T>。 DataServiceQuery<T>是实现了IQueryable<T>接口的。
怎么样?是不是感觉世界又美好了许多。呵呵。
=============================
好了,就到这了。晚安 to you and to me ...