我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:白小姐 > 分布式应用 >

如何搭建NET Entity Framework分布式应用系统框架

归档日期:07-03       文本归类:分布式应用      文章编辑:爱尚语录

  1. 通过远程客户端传输过来的实体,都是处于分离状态(entitystate属性值为detached),所以在多层应用程序中的服务端实现实体的更新或删除时,关键是如何把实体附加回实体容器中。msdn上关于对分离实体的查询和cud操作描述如下:

  在实体框架的某个对象上下文内执行查询时,返回的对象会自动附加到该对象上下文。还可以将从源而不是从查询获得的对象附加到对象上下文。您可以附加以前分离的对象、由 notracking 查询返回的对象或从对象上下文的外部获取的对象。还可以附加存储在 asp.net 应用程序的视图

  · 调用 objectcontext 上的 addobject 将对象附加到对象上下文。当对象为数据源中尚不存在的新对象时采用此方法。

  · 调用 objectcontext上的 attach 将对象附加到对象上下文。当对象已存在于数据源中但当前尚未附加到上下文时采用此方法。有关更多信息,请参见如何:附加相关对象(实体框架)。

  · 调用 objectcontext上的 applypropertychanges。当对象已存在于数据源中,并且分离的对象具有您希望保存的属性更新时采用此方法。如果简单地附加该对象,则属性更改将丢失。有关更多信息,请参见如何:应用对已分离对象的更改(实体框架)。

  2. 实现动态条件查询。在本地环境中,对于linq,我们可以通过动态构造lambda表达式树来实现动态条件查询,但是在远程环境中,lamdba表达式不支持远程序列化传输,只能通过objectcontext的createquery方法实现,但幸好微软后来又提供了一个linq动态查询扩展库dynamic.cs,使用起来更方便,于是采用它实现。

  3. ef中核心抽象类是objectcontext,实体容器都从它派生,实体容器上的cud方法其实都是通过调用objectcontext的cud操作方法实现的。

  2) applypropertychanges(string,object)表示把分离状态的实体object上的所作的修改更新回容器中已存在的对应的实体,执行条件有两个:①实体处于分离状态,②实体容器中存在主键值与其相同的且为unchanged状态的实体,所以,当我们需要更新一个detached状态的实体时,可以先把一个具有原始值的相同键值的实体附加回容器中,或者直接执行一下查询,从数据库中取出该实体。

  3) deleteobject(object)表示从实体容器中删除一个实体,执行条件是该实体存在于实体容器中,所以删除一个detach状态的实体之前,需要把它通过attach方法附加回实体容器中。

  4. 实体对象也是基于抽象类entityobject派生的,由此我们完全可以用contextobject和entityobject实现服务端对实体的查询和cud方法,其实现子类在运行时由客户端注入,从而使服务端和数据库实现松耦合。

  新建一个解决方案efservicesystem,添加一个新项目,命名为efmodel,添加项目,在项目下添加一个ado.net entity data model项,命名为efmodel.edmx,选择从数据库生成(假设我们已经建好了一个sql server数据库),一路点击下一步,直至完成。编译项目成功后就算完成。为什么要把数据库模型单独编译成一个dll呢,我将在后面给予解释。

  1) 利用外观模式,我们把客户端常用的查询和cud操作方法简化为3个方法queryt,save(t t),delete(t t),根据针对接口编程的设计原则,定义一个cud方法接口供客户端调用。

  2) 实现类entityhelper的代码。主要思路是通过构造函数注入数据上下文实例名称,在配置文件取出其程序集限定名,

  3) 最后,我们创建一个服务工厂类,暴露给客户端,负责以接口方式向客户端提供远程服务对象,数据服务层创建完毕。

  3. 创建运行服务的宿主程序。实际开发中,通常选择创建一个windows服务程序来运行remoting,但是服务需要安装才能启动,运行和调试起来都比较繁琐,所以这里创建一个简单的控制台程序来运行它。在解决方案下添加一个控制台程序项目,在program.cs编写如下代码:

  配置文件fig主要包括数据库连接信息以及自己定义一个数据上下文名称(这里和数据库连接名称相同,事实上不必相同),数据库连接信息可以从efmodel项目中配置文件中直接拷贝过来。内容如下:

  4. 最后,我们建立一个winform客户端作为测试。在program.cs注册远程服务:

  添加一个窗体form1,放入一个按钮,在按钮点击处理事件里加入下面的代码,示范客户端如何调用远程服务类实现查询和cud操作,简单起见,我不演示数据库的数据变化了,反正,看代码,你懂的。

  1. 至此,整个系统搭建完毕。在本例中,我把所有项目都统一建立在一个解决方案下,其实是为了演示方便,实际开发时候,完全可以各自独立创建。下面我们来分析一下各个项目的职能和相互之间的引用关系。

  1) efmodel:由visual studio 的数据模型工具生成的数据库实例模型,提供数据的查询以及cud操作。不需引用其它项目。

  2) efservice:使用数据库实例模型以及实体的抽象基类编写完成,代码里不涉及具体数据库模型实例,运行时通过客户端注入参数和读取配置文件动态生成数据库模型实例,并调用实例的查询和cud方法实现客户端的请求。不需引用其它项目。

  3) efservicehost:负责运行remoting服务,如果通过配置文件方式发布服务的话,编译时也不需引用其它项目,我这里引用了efservice项目,是因为使用了代码方式暴露efsservice的服务类。运行时需要将efservice和efmodel的dll文件拷贝至运行目录下。

  4) efclient:需要引用efmodel和efservice。(注:因为本例中式使用了remoting作为远程服务,如果是webservice或者wcf则只需添加服务引用,然后在本地生成客户端代理类)。事实上efservice中的实现类entityhelper也可以独立出去,不必让客户端引用,对于客户端而言,仅仅是使用servicefactory和接口ientityhelper就足够了。这样只要接口不变,entityhelper更新的时候,客户端无须更新引用,而且服务端代码可以完全被隔离开客户端,对一些服务端和客户端之间的保密性比较敏感的项目尤为有利。

  2. 通过分析我们发现,在开发下一个新项目的时候,即使整个数据库都变了,从sql server变成oracle,数据库服务名变了,表也变了,我们仍然无需修改服务端代码,只需针对新的数据库,生成新的efmodel,然后拷贝dll文件至efservicehost的运行目录下(这也就是我为什么要把efmodel独立成一个项目的原因),再修改一下efservicehost的配置文件中的数据库连接和实体容器名称即可完成新系统的部署。对于客户端来说,也就是更新一下efmodel.dll,还是调用服务端提供的那几个api,便可完成查询和cud操作,不用关心底层的数据库是sql server还是oracle,更不用自己实现对新库新表的查询和cud操作(本来也不用)。当然,对于正在运行的系统,我们也可以针对新建数据库生成新的实体模型dll,拷贝至efservicehost运行目录下,实现热插拔方式扩展数据库,而对原来的系统毫无影响,即使新加的库是不同类型的库。

本文链接:http://frankstella.net/fenbushiyingyong/665.html