rafy领域实体框架演示-改造传统应用程序v1_第1页
rafy领域实体框架演示-改造传统应用程序v1_第2页
rafy领域实体框架演示-改造传统应用程序v1_第3页
rafy领域实体框架演示-改造传统应用程序v1_第4页
rafy领域实体框架演示-改造传统应用程序v1_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、VER: 201310 -1.0Rafy 领域实体框架演示用程序-改造传统应Ver1.3访2013/11/291 / 26VER: 201310 -1.0目录摘要3原程序说明3程序转换5转换方案51. 使用UML 进行领域建模62. 升级.NET 版本73. 添加Rafy 领域实体项目74. 实体转换95. 简单实体的转换96. BLL、DAL 层代码转换107. 外键关系的转换138. 使用组合实体13转换后实体项目结构15新功能展示16自动生成数据库16已执行的 SQL 语句16领域实体关系图17以C/S 方式部署程序19以SQLCE 方式部署程序242 / 26VER: 201310 -

2、1.0摘要本文通过使用 Rafy 领域实体框架来改造一个传统的三层架构应用程序 “服装进销存”系统,来讲解如何使用 Rafy 领域实体框架进行数据库应用程序的快速开发,以及替换为使用 Rafy 框架后带来的一些新功能。原程序说明考虑到要更好地演示如何使用 Rafy 框架来开发一个传统的管理系统,决定挑选一个开源系统进行改造,而这个系统应该是简单、常见的三层架构,这种系统大家都比较熟悉,这样就可以更加快速的理解框架的使用了。在开源上挑选了很久,免费的三层架构系统挺多,但是许多系统并不规范。一些系统虽然写着使用三层架构,但是金玉其外,败絮其中,看上去非常正式的系打开源码,界面层代码中就可以看到直接

3、编写的 SQL 语句。最终,我 选 用 了 知 名 度 服 装 进 销 存 管 理 系 统 , 源 代 码地 址 :htt/Code/ZhiMingDuClothesSys。该系统三层间的调用比较严格,业务也非常简单。系统功能描述:操作员管理,供应商管理,顾客管理库存:库存管理,库存盘点销售:服装销售,服装退货服装:服装类别,服装登记销售:销售统计,利润统计技术特点:使用了三层架构设计程序,更换底层数据库类型方便。系统使用了 SqlLite 作为数据库,后可以直接运行。界面截图 :3 / 26VER: 201310 -1.04 / 26VER: 201310 -1.0程序转换转换方案原系统是简

4、单的三层架构:而会使用的架构,来改造整个系统:Rafy5 / 26VER: 201310 -1.0对于一个依赖关系较为严格的三层系统来说,要使用 Rafy 框架来替换其中的数据层、业务逻辑层以及界面查询的功能,是比较简单的。本次转换,我按照以下步骤进行:1.理解系统需求,使用 UML 画出领域实体间的关系。2.添加 Rafy 领域实体项目。3.根据实体的关系图,在实体程序集中添加对应的实体及实体间的关系;同时也可以把旧表中的属性添加到实体中。4.把所有跨多表的业务逻辑转换为领域服务。5.依次把历史的实体删除,转而使用新的查询、领域服务。实体,以及其对应的实体Rafy接下来,就正式对代码进行转换

5、:1. 使用 UML 进行领域建模经分析,原系统拥有以下领域模型:User:用户;Company:供应商;Customer:顾客;GoodCategory:商品类别;Good:商品(服装);Stock:入库信息;Regood:返库信息;Bill 及 Sell:销售单据及销售明细。它们的关系如下:6 / 26VER: 201310 -1.0(虽然原系统中一些实体的名称取得并不合理,但是为了简化系统的转换工作,新系统中的类命名还是保持和原系致。)关于哪些关系应该使用组合关系来进行设计,大家可以查看 Rafy 用户向导文档中的“领域实体框架/领域实体/实体关系”章节。2. 升级 .NET 版本在开始

6、转换代码前,由于原程序使用的是 .NET 2.0 的运行时,而 Rafy 要求必须使用 .NET 4.0。所以版本。需要把解决方案中的每个项目都转换为 .NET 4.0需要注意的是,由于原程序使用的 SqlLite 只支持 2.0 版本。同时,需要把SqlLite 替换为.NET 4.0 的版本。3. 添加 Rafy 领域实体项目在解决方案中添加一个 Rafy 领域实体项目, 命名为 CS( 为原系统名ClothesSys 的缩写)。7 / 26VER: 201310 -1.0点击确定后生成的项目如下:8 / 26VER: 201310 -1.0接下来,会在这项目中添加领域实体与领域服务,来替

7、换原程序中除界面项目以外的其它几个项目:4. 实体转换接下来,依次把历史的实体删除,转而使用新的 Rafy 实体。这一步,需要按照依赖关系,尽量先转换不依赖其他实体的实体,即按照以下顺序进行转换:、pany、Customer、GoodCategory、Good、Stock、Regood、Bill 和 Sell。由于 Bill 和 Sell 有强聚合关系,所以放到最后一起转换。(在变更每一个实体时,原代码中所有的 BLL 查询,都需要在实体仓库中编写相关的代码支持;业务逻辑则需要编写领域服务)实体的转换分为以下几类:无关系实体的转换有关系实体的转换组合实体的转换5. 简单实体的转换简单实体没有复

8、杂的关系,只是一个简单的表。在转换为 Rafy 实体时,只需要把表中的所有属性都添加到实体中就可以了。在编写时,需要注意的是:标识转换为 Rafy 实体后,所有的实体都继承自 Entity 类型。Entity 类了类型的 Id 属性作为所有实体的标识属性,这个属性会在数据库中生成一个自增长的主键列。旧实体类上的所有主键列、唯一列,在新实体中都变成了普通列。实体属性的唯一性验证,需要放到实体之上的业务逻辑层中来完成。属性原实体的所有属性,在 Rafy 实体中都使用属性代码段来生成同名的实体属性代码即可。9 / 26VER: 201310 -1.06. BLL、DAL 层代码转换转换查询数据的代码

9、在原代码中 BLL、DAL 两层中,都有许多的查询方法。这些方法都需要转换为新代码中对应实体的实体仓库中的查询方法。例如,原程序中通过顾客询顾客的查询方法:查public sic Customer GetCustomerById(string id)Customer ct = null;Parameter sqlparams = newParameternewParameter(customerId,id);DataReader sdr =Helper.GetReader(select * from T_customerwhere customerid=customerId, sqlparam

10、s);if (sdr.Read()ct = new Customer();ct.CustomerID = sdr.GetValue(0).ToString();ct.CustomerName = sdr.GetValue(1).ToString();ct.Socre = Convert.To32(sdr.GetValue(2);ct.Remark = sdr.GetValue(3).ToString();sdr.Close();return ct;需要转换为 Rafy 实体仓库中的新方法:public Customer GetByCustomerId(string id)return this

11、.Fetch(new PropertiesMatchCriteria Customer.CustomerIDProperty, id ,);转换业务逻辑代码BLL、DAL 中,除了查询方法以外,剩下的还有一些简单对实体的增、删、改操作。这些操作已经在实体仓库基类中实现了,所以可以不用转换。10 / 26VER: 201310 -1.0除了简单的 CRUD 操作外,系统中还有一些需要同时操作多个表的事务操作,原系统把这些业务逻辑都写到了数据层中。例如 ReGoodService.ReGoodSumbit方法:public sic bool ReGoodSumbit(ReGoods regoods

12、)Parameter sqlparams = newParameternewnew new new new new new newnewParameter(regoodsId,regoods.ReGoodsID),Parameter(regoodsNum,regoods.ReGoodsNum), Parameter(regoodsPrice,regoods.ReGoodsPrice), Parameter(reNeedPay,regoods.ReNeedPay), Parameter(reRealpay,regoods.ReRealPay), Parameter(regoodsResult,r

13、egoods.ReGoodResult),Parameter(userId,regoods.UserId),Parameter(sellId,regoodlId),Parameter(regoodsTime,regoods.RegoodsTime.ToString(yyyy-MM-ddHH:mm:ss);string sql = insertoT_regoods(regoodsid,regoodsNum,regoodsPrice,reNeedPay,reRealPay,regoodsResult,userId,regoodsTime,sellId) ; sql+=values(regoodsi

14、d,regoodsNum,regoodsPrice,reNeedPay,reRealPay, rego odsResult,userId,regoodsTime,sellId);tryConnection con =Helper.GetConnection();Tranion trans = con.Begranion();Helper.ExecuteNonQuery(trans, sql, sqlparams);CustomerService.DecreaseCustomerScore(trans, regoods);StockService.IncreaseStocskNumByGoodI

15、d(regoods.ReGoodsID, regoods.ReGoodsNum);mit();return true;catch (Exception ex)return false; throw ex;11 / 26VER: 201310 -1.0可以看到,这段代码中,不但有业务逻辑的控制,还有数据库连接的控制,事务的控制,Sql 语句的拼装。显得非常。而这种业务逻辑,在 Rafy 框架中,可以使用领域服务来实现。例如,刚才的逻辑,被替换为以下代码:Serializablepublic clasbmitRegoodService : Servicepublic Regood Regood g

16、et; set; protected override Result ExecuteTranion()if (Regood = null) throw new ArgumentNullException(Regood);if (!Regood.IsNew) throw new ArgumentNullException(Regood);RF.Save(Regood);/修改库存Regood.Good.StockSum += Regood.ReGoodsNum; RF.Save(Regood.Good);/减少客户的积分var ct = Regood.Sell.Customer; if (ct

17、!= null)ct.Score -= Regood.ReRealPay; RF.Save(ct);return true;可以看到,使用 Rafy 领域服务来实现后有以下好处:整个代码非常直接地表现了业务逻辑,没有一点多余的代码。使用了实体属性的懒加载功能, 使得程序可以直接使用如Regood.Sell.Customer 这样的强关系。方便通用代码的封装。例如,事务的控制已经交给了服务基类来处理。12 / 26VER: 201310 -1.0业务逻辑独立封装。每一个单独的业务都是一个服务对象,方便管理。为 SOA 提供了架构基础。同时,使用领域服务还可以方便地直接使用 C/S 架构来部署。7

18、. 外键关系的转换旧表中的外键间的关系,在设计关系,除了 Bill(销售单) 与 Sell(销售明细) 两个表UML 时,都设计为实体间的关系。先区分清楚关系的可空性,然后就可以在相应实体中编写到 Good(商品)的关系,被转换为下面这个实体属性了。例如,Stock(库存)实体属性:public sic readonly RefIdProperty GoodIdProperty =P.RegisterRefId(e = e.GoodId, ReferenceType.Normal);publicget setGoodIdreturn this.GetRefId(GoodIdProperty);

19、 this.SetRefId(GoodIdProperty, value); public sic readonly RefEntityProperty GoodProperty =P.RegisterRef(e = e.Good, GoodIdProperty);public Good Goodget return this.GetRefEntity(GoodProperty); set this.SetRefEntity(GoodProperty, value); 8. 使用组合实体Bill 和 Sell 分别表示销售订单、销售明细项。设计为组合实体后,在使用时,可以直接以组合实体的方式构

20、造、保存、更新、删除,非常方便。例如,在添加销售信息界面中的代码如下:var bill = new Bill();bill.UserId =bill.BillTimeuserId;= now;foreach (Sellsell in list)sell.CustomerId = customerId;sell.SellTime = now;bill.SellList.Add(sell);13 / 26VER: 201310 -1.0var svc = new AddBillService Bill = bill ;svc.Invoke(); if (svc.Result)MessageBox.

21、Show(提交订单成功!, 提示);this.Close(); ucGSM.bindDgvSellRecordToday();先构造了组合对象,然后提交给领域服务息逻辑。此服务代码如下:以执行添加销售信AddBillServiceSerializablepublic class AddBillService : Servicepublic Bill Bill get; set; protected override Result ExecuteTranion()if (Bill = null) throw new ArgumentNullException(Bill);if (!Bill.Is

22、New) throw new ArgumentException(Bill);/调用仓库保存整个销售单var repo = RF.Concrete();reave(Bill);/修改库存foreach (var sell in Bill.SellList)sell.Good.StockSum -= sell.SellNum; RF.Save(sell.Good);/添加客户的积分var ctRepo = RF.Concrete();ctReave(ct);14 / 26VER: 201310 -1.0return true;转换后实体项目结构待每一个实体修改并替换完毕后,再删除原来的传统三层项

23、目后,解决方案中就只剩下了两个项目,一个领域实体项目“CS”;一个原程序中的界面层Rafy项目“ClothesSys”。截止到现在,已经完成了常的运行,实现了与原系ClothesSys 的完整转换。转换后的系统已经可以正致的功能。该示例代码后,只需要修改 app.config 文件中的连接字符串中的用户名后,就可以直接运行示例,程序即会自动创建数据库并成功运行!和15 /26VER: 201310 -1.0新功能展示接下来,展示转换为使用 Rafy 实体框架后,带来的新功能。自动生成数据库在程序转换转换完毕后。由于已经配置好数据库的连接字符串,所以直接运行整个程序,Rafy 会同时生成对应的数

24、据库、表、字段,以及相应的外键关系等。该库满足数据库的第三范式要求。同时,开发过程中新添加的属性,也会每次自动同步到这个数据库中。以下是服装管理系统生成的数据库结构图:已执行的框架可以SQL 语句所有运行过程中执行的 Sql 语句及相关日志。这对于开发做系统调试、性能优化提供了较好的帮助。该功能需要手动打开。在配置文件中添加以下配置:16 / 26VER: 201310 -1.0配置项的值是用于日志的文件的地址。这时,再运行整个程序,就会发现 D 盘下的 SQLTraceLog.txt 文件已经开始了。整个程序所有执行的SQL的格式如下:2013/10/30 10:23:42Database:

25、 ClothesSysSELECT User.Id,User.Name,User.Password,User.UserNameFROM UserWHERE User.UserName = p0ORDER BY User.Id ASCParameters:rafy领域实体关系图在安装了 RafySDK 后,可以使用领域实体关系图,以图形的形式来描述指定的部分实体及实体间的关系。例如,在 CS 项目中Entities 文件夹内,添加新项,选择 Rafy -MDesigner,命名为 CS M.odml:17 / 26VER: 201310 -1.0在打开的文档中点击“添加实体类”按钮,在弹出的窗口

26、中选择除基类外所有的领域实体类:点击确定后,图中便自动为所选实体生成了对应的关系图,稍加调整即可:18 / 26VER: 201310 -1.0在图中可以清晰地看出:Bill 与 Sell 是组合关系,而其它的实体间的关系的名称、可空性等。这些关系,与在转换之初的设计是完全一致的。以 C/S 方式部署程序截止到现在,开发好的 Rafy 应用程序都是采用直接连接数据库的模式。接下来,将通过一些简单的调整,使得这个应用程序支持以 C/S 架构部署。整个过程只需要少量的代码:19 / 26VER: 201310 -1.0添加服务端控制台应用程序项目在整个解决方案中添加一个新的控制台应用程序,取名为

27、ServerConsole:为项目添加所有 Rafy 程序集、CS 实体程序集以及 System.ServiceM程序集的:20 / 26VER: 201310 -1.0在 Main 函数中添加以下代码,启动服务端领域项目,并开始口:WCF 端usingusing using using using using using usingSystem;System.Collections.Generic; System.Linq; System.ServiceM; System.Text;CS;Rafy;Rafy.;namespaclassserverConsoleProgramic void M

28、ain(string args)Plugnewable.Libraries.AddPlugin();App().Startup();using(ServiceHost serviceHost = newServiceHost(typeof(Rafy.DataPortal.WCF.ServserviceHost.Open();ortal)Console.Wriine(Press to terminate service);Console.ReadLine();serviceHost.Close();然后,为本项目添加应用程序配置文件 App.config,代码如下:add name=CS con

29、nectionString=server=.SQLExpress;database=ClothesSys;uid=sa;pwd=GIX4 providerName=System.Data.SqlCnt/ortalVER: 201310 -1.0/system.serviceM修改客户端应用程序连接方式接下来需要把界面程序变更为连接服务端。打开 ClothesSys 项目中的Program.cs 文件,修改为以下代码:sic class Program/ / 应用程序的主点。/Sshreadic void Main()Plugnew Cable.ntLibraries.AddPlugin();A

30、pp().Startup();Application.EnableVisualStyles();patibleTextRenderingDefault(false); Application.Run(new formLogin();/ / 客户端使用的应用程序类型。/ public class CntApp :Appprotected override void InitEnvironment()RafyEnvironment.Location.DataPortalMode = DataPortalMode.ThroughService;base.InitEnvironment();RafyEnvironment.Location.DataPortalMode 表示连接数据的模式, 默认值是DataPortalMode.ConnectDirectly(直接连接数据库),CApp 类把该值nt变更为 DataPortalMode. Throu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论