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枚举值比较简单:见名知意,所以不多讲了。

EFWCFService
 1  public class EFWCFService : DataService< NorthwindEntities >
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 config.SetEntitySetAccessRule("*",EntitySetRights.All);
12 config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
13 }
14 }

浏览器显示如下:

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事件:代码如下:

View Code
 1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using EFWCFTest.EFWCFReference;
10
11 namespace EFWCFTest
12 {
13 public partial class Form1 : Form
14 {
15 public Form1()
16 {
17 InitializeComponent();
18 }
19
20 private void btnFill_Click(object sender, EventArgs e)
21 {
22 NorthwindEntities svc = new NorthwindEntities(new Uri("http://localhost:1713/EFWCFService.svc/"));
23 foreach (Category c in svc.Categories)
24 {
25 this.lboxCategory.Items.Add(string.Format("{0}::{1}",c.CategoryID,c.CategoryName));
26 }
27 }
28 }
29 }

注意:

代码第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 ...

posted @ 2011-12-25 22:05  MarkSun  阅读(4282)  评论(13编辑  收藏  举报