和我一起学CSLA.NET----创建业务对象2

上一节我们已经创建了我们业务对象的属性和简单的验证规则,这一节我们主要来实现数据门户 ,首先先大概介绍一下CSLA数据访问相关的概念:
    Csla框架的数据门户通过通道适配器模式和消息路由模式 合并起来,提供了对服务器上所有数据访问操作的一个简单明了的入口点。实际上,数据门户完全隐藏了服务器的参与,这就使得应用程序能在不改变代码的情况下,在两层和三层物理部署之间自由切换。数据门户有以下特点:
    
实现了移动对象
     隐藏了网络传输(通道适配器)
     暴露了对服务器的唯一入口点(消息路由)
     暴露了服务器端资源(数据库引擎、分布式事务等)
     统一了上下文(在客户端和服务器之间传递上下文)
    数据门户强制了你的对象和数据访问层或者是ORM交互的标准和结构. 这个标准化保留了灵活性,使你能够自由的使用几乎任何你选择的数据访问技术,包括但不仅限于 :      
    纯ADO.NET(Connection,data readers等)
    DataSet和TableAdapter对象
    LINQ to SQL
    LINQ to XML
    ADO.NET Entity Framework
    Nhibernate  和其它第三方ORM工具
    简单的文件I/O
    远程XML或者是JSON服务

   CSLA的数据访问门户的标准就是每个业务对象提供DataPortal_XYZ方法,负责进行创建、提取、添加、更新和删除,然后在业务对象工厂方法中调用数据门户的对应方法就是转换成调用提供的DataPortal_XYZ方法:
   fig02
一个完整的可编辑的对象一般要实现如下几个数据门户的方法(这部分代码可以放到业务对象类中、分离在单独的类中、分离在单独的程序集中、使用对象工厂方法):
   DataPortal_Create()      对象被创建时将会被调用,在这里可以设置默认值.
   DataPortal_Fetch()        被数据门户调用来装载对象的数据
   DataPortal_Insert()       处理新对象的持久化保存
   DataPortal_Update()      处理脏对象的持久化更新
   DataPortal_DeleteSelf()
   DataPortal_Delete()        CSLA提供了两种删除对象的方法:立即删除 延迟删除. 延迟删除就是说在对象被装载到内存中的时候,IsDeleted属性被设置成true,当调用对象的Save()时,这时候会在内部调用 DataPortal_DeleteSelf方法。立即删除是指显示调用DataPortal.Delete方法并且传递标志要删除对象的查询条件, 数据门户DataPortal在内部会调用此对象的DataPortal_Delete方法.
   我们一个一个的来实现以上几个方法,首先是DataPortal_Create:

隐藏行号 复制代码 Product.DataPortal_Create
  1. [RunLocal
    ()]
  2. protected override void 
    DataPortal_Create()
  3. {
  4.     using 
    (BypassPropertyChecks)
  5.     {
  6.         ProductID = Guid
    .NewGuid().ToString();
  7.         ValidationRules.CheckRules();
  8.     }
  9. }

    1. [RunLocal()]特性标明此方法在本地运行,而不是在应用服务器上运行,这在分布式服务器部署上能够缩短处理时间.
    2. 由于此方法没有数据库相关的操作,只是简单的属性值初始化,没有必要调用服务器的相关资源,所以才会使用[RunLocal()]标明在本地运行,假如你需要调用数据库资源来进行初始化的话,就不需要打RunLocal标签了.
    3. Product业务对象只需要给主键生成一下Guid字符串,然后我们会手动调用ValidationRules.CheckRules验证一下此业务对象是否符合校验规则.
    4. BypassPropertyChecks是新增的特性,因为在上一节我们介绍过,如果直接通过Name = "TestName"其实是调用的GetProperty,这样在内部会进行一些检查,如果需要在业务对象内部给属性赋值的话,为了性能或者其它原因,想 绕过安全或者其它检查,一般需要这样写
        LoadProperty<string>(NameProperty, "TestName")
而现在可以直接使用BypassPropertyChecks, 是不是这样方便多了.
     
    接下来添加DataPortal_Fetch:

隐藏行号 复制代码 Product.DataPortal_Fetch
  1. private void 
    DataPortal_Fetch(SingleCriteria
    <Product
    , string
    > criteria)
  2. {
  3.     using 
    (var 
    ctx =
  4.       ContextManager
    <CSLADemo.DalLinq.CSLADemoDataContext
    >.
  5.       GetManager(CSLADemo.DalLinq.Database
    .CSLADemo))
  6.     {
  7.         var 
    data = (from 
    p in 
    ctx.DataContext.Products
  8.                     where 
    p.ProductID == criteria.Value
  9.                     select 
    p).Single();
  10.         using 
    (BypassPropertyChecks)
  11.         {
  12.             ProductID = data.ProductID;
  13.             ItemName = data.ItemName;
  14.             ItemNo = data.ItemNo;
  15.         }
  16.     }
  17. }

     1.参数为SingeCriteria,其实是表明能够代表当前业务对象的标识,在这里业务对象是Product,主键是string类型,如果在这里你的主键为多个(一般不推荐)的话,你需要实现自己的Criteria。
     2.这里包含根据ProductID获取Product对象的linq实现,在这里就不详细介绍了,其中CSLADemo.DalLinq.Database中的CSLADemo变量存储的是数据库的名字

    我们再来添加DataPortal_Insert: 

隐藏行号 复制代码 Product.DataPortal_Insert
  1. [Transactional
    (TransactionalTypes
    .TransactionScope)]
    
  2.        protected override void 
    DataPortal_Insert()
    
  3.        {
    
  4.            using 
    (var 
    ctx =
    
  5.              ContextManager
    <CSLADemo.DalLinq.CSLADemoDataContext
    >.
    
  6.              GetManager(CSLADemo.DalLinq.Database
    .CSLADemo))
    
  7.            {
    
  8.                using 
    (BypassPropertyChecks)
    
  9.                {
    
  10.                    var 
    data = new 
    CSLADemo.DalLinq.Product
    ();
    
  11.                    data.ProductID = ReadProperty(ProductIDProperty);
    
  12.                    data.ItemNo = ReadProperty(ItemNoProperty);
    
  13.                    data.ItemName = ReadProperty(ItemNameProperty);
    
  14.                    ctx.DataContext.Products.InsertOnSubmit(data);
    
  15.                    ctx.DataContext.SubmitChanges();
    
  16.                }
    
  17.                FieldManager.UpdateChildren(this
    );
    
  18.            }
    
  19.        }
    

     1.[Transactional()]特性用来保证此方法事务性.
     2.当调用业务对象的Save方法时,如果此对象的IsNew=True,数据门户会自动调用此方法.
     3.FieldManager.UpdateChildren(this)是指在更新完后,更新所有的子对象,这个在后面介绍
 
   同样的,我们添加另外三个数据门户方法:

隐藏行号 复制代码
  1. [Transactional
    (TransactionalTypes
    .TransactionScope)]
    
  2.         protected override void 
    DataPortal_Update()
    
  3.         {
    
  4.             using 
    (var 
    ctx =
    
  5.                 ContextManager
    <CSLADemo.DalLinq.CSLADemoDataContext
    >.
    
  6.                 GetManager(CSLADemo.DalLinq.Database
    .CSLADemo))
    
  7.             {
    
  8.                 using 
    (BypassPropertyChecks)
    
  9.                 {
    
  10.                     var 
    data = new 
    CSLADemo.DalLinq.Product
    ()
    
  11.                     {
    
  12.                         ProductID = ReadProperty(ProductIDProperty)
    
  13.                     };
    
  14.                     if 
    (IsSelfDirty)
    
  15.                     {
    
  16.                         data.ItemNo = ReadProperty(ItemNoProperty);
    
  17.                         data.ItemName = ReadProperty(ItemNameProperty);
    
  18.                         ctx.DataContext.Products.Attach(data, true
    );
    
  19.                     }
    
  20.                 }
    
  21.                 FieldManager.UpdateChildren(this
    );
    
  22.                 ctx.DataContext.SubmitChanges();
    
  23.             }
    
  24.         }
    
  25.         [Transactional
    (TransactionalTypes
    .TransactionScope)]
    
  26.         protected override void 
    DataPortal_DeleteSelf()
    
  27.         {
    
  28.             DataPortal_Delete(
    
  29.               new 
    SingleCriteria
    <Product
    , string
    >(ProductID));
    
  30.         }
    
  31.         [Transactional
    (TransactionalTypes
    .TransactionScope)]
    
  32.         private void 
    DataPortal_Delete(SingleCriteria
    <Product
    , string
    > criteria)
    
  33.         {
    
  34.             using 
    (var 
    ctx =
    
  35.               ContextManager
    <CSLADemo.DalLinq.CSLADemoDataContext
    >.
    
  36.               GetManager(CSLADemo.DalLinq.Database
    .CSLADemo))
    
  37.             {
    
  38.                 var 
    data = ctx.DataContext.Products
    
  39.                      .Single(r => r.ProductID == criteria.Value);
    
  40.                 ctx.DataContext.Products.DeleteOnSubmit(data);
    
  41.                 ctx.DataContext.SubmitChanges();
    
  42.             }
    
  43.         }
    

     1.DataPortal_Delete为private,因为它不并不会被自动调用。在这里,提供了延迟加载功能,所以在DataPortal_DeleteSelf里调用DataPortal_Delete.

 代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值