在当初搭建项目架构时.考虑到把数据访问和UI分离利用Silverlight RIA Services Class Library类库来搭建底层数据访问. 同时页面显示数据格式较多. 有一部分采用绑定方式.所以用到MVVM[Module-View-ViewModule]框架比较容易, 这样既是把MVVM框架和Ria Service数据访问混合到一块.项目结构:
说明项目结构:
HROA_Services:Silverlight RIA Services Class Library类库 [Ria数据访问]
HROA_Controls:Silverlight项目中常用自定义控件.
HROA_Entitys:MVVM中Module层
HROA_UI:MVVM中View层
HROA_ViewModules:MVVM中ViewModule层.
HROA_UI.Web:sliverlight UI承载.
既然实际需求中UI[MVVM中View]层数据显示样式偏多.UI应该可定制的.MVVM框架正是从WPF的MVP[Model-View-Presenter]模式演变而来.数据绑定和ViewModule相结合突出简单实用 容易操作. 同时把UI与业务逻辑进行分离出来. ViewModule中保存着UI的特有属性和调用接口.并由一个ViewModule视图同属性进行绑定. 形成松散的耦合. 个人直观理解:
其实MVVM基于事件绑定机制, 在View层中只要完成绑定即可,View会自动更新Model,Model再通知Control,这样就可大量减少View 层中的Control代码. 回想一个WebForm开发View层中需要编写大量控制页面代码.移植和可重用性很低,导致做了很多重复性工作,MVVM恰恰在一定程度上简化这样混乱结构.
在项目走到三分之一时.碰到系统核心业务操作. DomainService基于原始四个增删改查数据操作方法已经是力不从心. 其实在项目刚开始时就一直想分析一下DomainService中多种数据操作.前门一章WCF Ria Service 理解制图版本【待续】中简单写了类库结构.今天具体分析DomainService中细节.
A:创建DomainService.
通过创建向导创建时.Enable editing默认不选中.直接创建DomainService则只自动生成1个查询方法.选中后则自动添加增删改查4个方法. 分析这4个自动生成方法:
各个方法返回值定义方式如上.DomainService不仅可以生成如上常用4个方法 也支持用户自定义方法.定义格式如下:
当然在DomainService 也支持Reslove和Invoke方法.定义语法如下:
在技术群里曾有人多次跟我提起 为什么我自定义一个方法返回值为一个Boolean值. 在调用时也用Boolean接受 总是报异常?.例如DomainService自定义:
- public bool islogin()
- {
- return "chenkai".Equals("chenkaige");//设定返回结果为False
- }
UI正确调用方式:
- //调用测试
- InvokeOperation<bool> getresinvoke = getdomain.islogin();
- string getresult = getresinvoke.Value.ToString();
接受类型应该为InvokeOperation<bool>,在DomainServer中自定义方法islogin并没有带标识属性UseCustomerMethod.但你可以显性的指定它为用户自定义方法.前面提到增删改查4个方法标识 有个在命名上有个特点:
当在4个方法中带了各自标识例如 更新方法前带了[Update]. 既是标识该方法为更新方法.同时该方法命名可以自定义 .如下:
- [Update]
- public void UpdateUserBaseInfor(Sl_Users getuser)
- {
- this.ObjectContext.Sl_Users.AttachAsModified(currentSl_Users, this.ChangeSet.GetOriginal(currentSl_Users));
- }
另外还必须提一点.发生数据冲突[并发]解析方法:
这个问题是在项目后期访问统计图数据遇到的.当多个用户同时更新一张表中同一条记录中相同字段时.DomainSErvice会提示一个异常. 其实这就是常见数据并发.在出现并发保存数据可以采用解析方法.这点对于一个稳定系统而言也很重要,解析方法使用.
- // 解析方法保存数据
- public bool ResolveSysteUser(Sl_Users currentUser,Sl_Users orginalUser,Sl_Users saveUser,bool isDeleteOperator)
- {
- return false;
- }
语法定义格式: ResolveSysteUser()参数:
第一个是当前用户实体, 第二个最初实体,第三个要保存实体,最后一个参数必须为Bool类型.注意:在此方法定义之前 必须定义该实体的更新方法.否则数据保存失败并提示一个异常.
另外DomainServer还可以定义另外两种类型方法:服务操作方法和一个规避方法使用的IgnoreOperator属性:
当你需要创建一个方法来操作更多数据或是这个操作方法对不依赖于默认定义CRUD[增删改查]方法 你可以适用ServiceOperator服务操作, 例如你可以用它来更新系统用户部分信息. 登录状态等需要动态更新. ServerOperator.参数必须相对应实体类型. 返回值为Void.但是如果要标识一个方法为ServiceOperator必须在方法前制定标识属性[ServiceOperator].如下:
- [ServiceOperation]
- public void ApproveExpenseReport( ExpenseReport expenseReport)
- {
- if (expenseReport.Status == 1)
- {
- if (expenseReport.EntityState == System.Data.EntityState.Detached)
- {
- Context.Attach(expenseReport);
- }
- expenseReport.Status = 2;
- }
- }
更多关于ServiceOperator操作请参见MSDN
IgnoreOperator应用场景为忽略DomainService中特定域方法.
有些时候.我们可以把一些定义DomainService中方法显示排除在外.不想让系统识别它是一个域方法.但仍定义在DomainService中. 既可以 在这些方法标识属性加上[IgnoreOperator] 于是系统把该方法识别一个可忽略方法.
注意[IgnoreOperator]可以用于DomainService中所有方法. 更多关于DomainService方法定义可以参见MSDN
本文转自chenkaiunion 51CTO博客,原文链接:http://blog.51cto.com/chenkai/764904