好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

DM层与Service层

DM层与Service层

首先分享一点自己最近的感悟:讨厌你的人总可以找到理由去讨厌你

正文开始

如果您是初次阅读这个系列,请先去《 Index & Writing Plan 》查找并阅读“ 架构设计系列” 的前两篇文章,顺序阅读会使您有更好的阅读体验

强烈推荐配合源代码阅读本文: 点击此处下载 (可以直接运行,会在本地自动生成数据库)

已经写完了Factory的实现。在Factory中,我们使用了预编译指令来实现了Model的切换:

 #define  A
 #if  B
 using   Model.B;
  using   DBaccess.B;
  #endif 
 #if  A
 using   Model.A;
  using   DBaccess.A;
  #endif 

切换Model,只需将#define A 修改为 #define B,非常方便(尽管要重新编译,还是让我有点不爽)

但是出现预编译指令的地方不宜过多——事实上,已经有一处要改就已经让我不爽了

所以,在DM层(数据操作层)与Service层(业务逻辑层)中,我们不能出现任何具体的Model的类名。

在本例中,就是DM和Service中不能出现类名:Teacher、Contact

因为每个出现了类Teacher和类Contact的地方,我们都要加上前文提到的预编译指令。而在实际项目中,这样做会导致切换Model要修改的地方非常多,可能会导致不可预期的错误

 

那么,DM层主要是用泛型来解决问题,代码如下:

 public   class   DMbase
    {
          protected   DbContext db;
          public   DMbase(DbContext db)
        {
              this .db =  db;
        }

          ///   <summary> 
         ///   select one
          ///   </summary> 
         ///   <typeparam name="T"></typeparam> 
         ///   <param name="entity">  这里的entity并无实际作用,只是用于编译器推敲类型  </param> 
         ///   <param name="predicate">  λ表达式  </param> 
         ///   <returns>  返回第一条匹配的记录,若无记录返回null  </returns> 
         public   virtual  T FindOne<T>(T entity, Func<T,  bool >  expression) 
              where  T :  class ,  new  ()
        {
              return   this .db.Set<T> ().FirstOrDefault(expression);
        }
        
          ///   <summary> 
         ///   select all
          ///   </summary> 
         ///   <typeparam name="T"></typeparam> 
         ///   <param name="entity">  这里的entity并无实际作用,只是用于编译器推敲类型  </param> 
         public   virtual  IQueryable<T> FindAll<T> (T entity) 
              where  T :  class ,  new  ()
        {
              return   this .db.Set<T> ();
        }

          public   virtual   void  Insert<T>( params   T[] entities)
              where  T :  class ,  new  ()
        {
              if  (entities !=  null  && entities.Length >  0  )
            {
                  var   set  =  this .db.Set<T> ();
                  foreach  ( var  item  in   entities)
                {
                      set  .Add(item);
                }
            }
        }

          public   virtual   void  Delete<T>( params   T[] entities)
              where  T :  class ,  new  ()
        {
              if  (entities !=  null  && entities.Length >  0  )
            {
                  var   set  =  this .db.Set<T> ();
                  foreach  ( var  item  in   entities)
                {
                      set  .Remove(item);
                }
            }
        }

          ///   <summary> 
         ///   提交事务
          ///   </summary> 
         public   void   Commit()
        {
              this  .db.SaveChanges();
        }
    } 

我的注释也说明了,其实FindOne方法和FindAll方法其实是不需要参数的,但是为了编译器推敲类型,传入了一个entity参数

在此要感谢下 xanthodont 同学,这个DM是在你的版本上改的,封装得很不错

 

写完DM层,接下来就是重头戏,Service层

下面的代码示范了如何取得所有的Teacher,并将Teacher与Contact对应起来

         public   object   FindAllTeacher()
        {
              //  取得一个Context 
             var  context =  ContextFactory.GetContext();

              //  从Factory中取得Teacher和Contact
              //  这里必须要用var 
             var  a =  ModelFactory.GetTeacher();
              var  b =  ModelFactory.GetContact();
              var  aList =  ModelListFactory.GetTeacherList();

            DMbase dm  =  new   DMbase(context);

              //  用之前取得的Teacher与Contact传入DM层,方便编译器推敲类型 
             var  contact =  dm.FindAll(b);
              var  teacher =  dm.FindAll(a);

              //  业务逻辑,将Teacher与Contact关联起来 
             var  result = teacher.Join(contact, o => o.ID, r => r.TeacherID, (o, r) =>  new  { tt = o, aa =  r });
            result  = result.OrderByDescending(o =>  o.aa.Email);

              //  处理数据 
             foreach  ( var  item  in   result)
            {
                a  =  item.tt;
                a.Contact  =  item.aa;
                aList.Add(a);
            }
              return   aList;
        } 

注意,这里我使用了Object作为返回类型 ,因为我其实不知道返回值是IList<Model.A.Teacher> 还是IList<Model.B.Teacher>,好在这里只需要一次拆装箱,无伤大雅

再来演示下如何插入:

         public   bool  AddTeacher<T, T1> (T teacher, T1 contact)
              where  T :  class , new  ()
              where  T1 :  class , new  ()
        {
              try  
            {
                  var  context =  ContextFactory.GetContext();
                DMbase dm  =  new   DMbase(context);
                dm.Insert(teacher);
                dm.Insert(contact);
                dm.Commit();

                  return   true  ;
            }
              catch  
            {
                  return   false  ;
            }
        } 

只有执行了dm.Commit(),两个Insert才会提交到数据库,保证了事务的一致性

就此搁笔

PS:昨天是博主生日,又老了一岁;有缘读到这里的园友,就别吝啬自己的祝福了吧 :)



/*=============================================================*/
作者: CrazyJinn
本文版权归作者和博客园共有,欢迎转载.但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 
如果看完这篇文章让您有所收获,请点击右下角"推荐". 
如果这篇文章让您觉得不知所云,或者通篇谬误,请点击右下角"反对".并且欢迎您留言给我提出宝贵的意见. 
如果您想获知我最新的动态,可以在绿色通道中点击"关注我".
/*=============================================================*/

分类:  .NET

标签:  设计 ,  架构

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于DM层与Service层的详细内容...

  阅读:47次