好得很程序员自学网

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

准备抽象NHibernate和EntityFramework

准备抽象NHibernate和EntityFramework

准备抽象NHibernate和EntityFramework

背景

考虑到目前中小企业应用的主流是ORM,我准备在NHibernate和EntityFramework之间找到一个抽象层,也就是说我准备只支持NHibernate和EntityFramework。

思路

NH和EF都实现了“工作单元”和“主键映射”这两种企业应用模式,而这两种模式其实就是管理一种状态机,如下图:

实现

工作单元接口

   1   using   System;
    2   using   System.Collections.Generic;
    3   using   System.Linq;
    4   using   System.Text;
    5   using   System.Threading.Tasks;
    6  
   7   namespace   Happy.Domain
    8   {
    9       ///   <summary> 
  10       ///   工作单元接口。
   11       ///   </summary> 
  12       ///   <remarks> 
  13       ///   聚合状态:
   14       ///   <list type="number"> 
  15       ///       <item>  transient:实例存在于内存中,但不存在于工作单元和数据库中。  </item> 
  16       ///       <item>  persistent in database:实例存在于数据库中。  </item> 
  17       ///       <item>  persistent in unitofwork:实例存在于工作单元中。  </item> 
  18       ///       <item>  detached:实例存在于内存和数据库中,但不存在于工作单元中。  </item> 
  19       ///   </list> 
  20       ///   合法转换:
   21       ///   <list type="number"> 
  22       ///       <item>  transient > Save -> persistent in unitofwork,Flush时会生成Insert Sql,场景:从UI层创建实例,执行创建。  </item> 
  23       ///       <item>  detached -> Update -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,执行修改(支持离线乐观并发)。  </item> 
  24       ///       <item>  detached -> Persist -> persistent in unitofwork,Flush时不会生成Sql,场景:将实例从另一个工作单元脱钩,添加到当前工作单元。  </item> 
  25       ///       <item>  detached -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从UI层重建实例,删除记录。  </item> 
  26       ///       <item>  detached -> Merge -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,合并到从数据库重建的实例,执行修改(不支持离线乐观并发)。  </item> 
  27       ///       <item>  persistent in unitofwork -> Evict -> detached,Flush时不会生成Sql,场景:将实例从当前工作单元脱钩,添加到另一个工作单元。  </item> 
  28       ///       <item>  persistent in unitofwork -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从数据库重建实例,删除记录。  </item> 
  29       ///       <item>  persistent in unitofwork -> Flush -> persistent in database,提交工作单元,会生成SQL,场景:执行完一系列Create、Update和Delete后统一提交,只产生一次数据库往返。  </item> 
  30       ///       <item>  persistent in database -> Load -> persistent in unitofwork,从数据库重建实例。  </item> 
  31       ///       <item>  persistent in database -> Refresh -> persistent in unitofwork,从数据库刷新实例,场景:使用存储过程修改了一个实例,使用此方法重新刷新一下。  </item> 
  32       ///   </list> 
  33       ///   </remarks> 
  34       public   interface   IUnitOfWork : IDisposable
   35       {
   36           ///   <summary> 
  37           ///   判断  <paramref name="item"/>  是否 persistent in unitofwork。
   38           ///   </summary> 
  39           bool  Contains<TAggregateRoot> (TAggregateRoot item)
   40               where   TAggregateRoot : AggregateRoot;
   41  
  42           ///   <summary> 
  43           ///   transient > Save -> persistent in unitofwork,Flush时会生成Insert Sql,场景:从UI层创建实例,执行创建。
   44           ///   </summary> 
  45           void  Save<TAggregateRoot> (TAggregateRoot item)
   46               where   TAggregateRoot : AggregateRoot;
   47  
  48           ///   <summary> 
  49           ///   detached -> Update -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,执行修改(支持离线乐观并发)。
   50           ///   </summary> 
  51           void  Update<TAggregateRoot> (TAggregateRoot item)
   52               where   TAggregateRoot : AggregateRoot;
   53  
  54           ///   <summary> 
  55           ///   detached -> Persist -> persistent in unitofwork,Flush时不会生成Sql,场景:将实例从另一个工作单元脱钩,添加到当前工作单元。
   56           ///   </summary> 
  57           void  Persist<TAggregateRoot> (TAggregateRoot item)
   58               where   TAggregateRoot : AggregateRoot;
   59  
  60           ///   <summary> 
  61           ///   执行如下两种转换:
   62           ///   <list type="number"> 
  63           ///       <item>  detached -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从UI层重建实例,删除记录。  </item> 
  64           ///       <item>  persistent in unitofwork -> Delete -> persistent in unitofwork,Flush时会生成Delete Sql,场景:从数据库重建实例,删除记录。  </item> 
  65           ///   </list> 
  66           ///   </summary> 
  67           void  Delete<TAggregateRoot> (TAggregateRoot item)
   68               where   TAggregateRoot : AggregateRoot;
   69  
  70           ///   <summary> 
  71           ///   detached -> Merge -> persistent in unitofwork,Flush时会生成Update Sql,场景:从UI层重建实例,合并到从数据库重建的实例,执行修改(不支持离线乐观并发)。
   72           ///   </summary> 
  73           void  Merge<TAggregateRoot> (TAggregateRoot item)
   74               where   TAggregateRoot : AggregateRoot;
   75  
  76           ///   <summary> 
  77           ///   persistent in unitofwork -> Evict -> detached,Flush时不会生成Sql,场景:将实例从当前工作单元脱钩,添加到另一个工作单元。
   78           ///   </summary> 
  79           void  Evict<TAggregateRoot> (TAggregateRoot item)
   80               where   TAggregateRoot : AggregateRoot;
   81  
  82           ///   <summary> 
  83           ///   persistent in unitofwork -> Flush -> persistent in database,提交工作单元,会生成SQL,场景:执行完一系列Create、Update和Delete后统一提交,只产生一次数据库往返。
   84           ///   </summary> 
  85           void   Flush();
   86  
  87           ///   <summary> 
  88           ///   persistent in database -> Load -> persistent in unitofwork,从数据库重建实例。
   89           ///   </summary> 
  90          TAggregateRoot Load<TAggregateRoot> (Guid id)
   91               where   TAggregateRoot : AggregateRoot;
   92  
  93           ///   <summary> 
  94           ///   persistent in database -> Refresh -> persistent in unitofwork,从数据库刷新实例,场景:使用存储过程修改了一个实例,使用此方法重新刷新一下。
   95           ///   </summary> 
  96           void  Refresh<TAggregateRoot> (TAggregateRoot item)
   97               where   TAggregateRoot : AggregateRoot;
   98  
  99           ///   <summary> 
 100           ///   回滚所有自上次提交以后的修改。
  101           ///   </summary> 
 102           void   Clear();
  103  
 104           ///   <summary> 
 105           ///   清空处于persistent in unitofwork状态的实例。
  106           ///   </summary> 
 107          TRepository GetRepository<TRepository> ()
  108               where   TRepository : IRepository;
  109       }
  110  }

基于EntityFramework的工作单元

   1   using   System;
    2   using   System.Collections.Generic;
    3   using   System.Linq;
    4   using   System.Text;
    5   using   System.Threading.Tasks;
    6   using   System.Data;
    7   using   System.Data.Entity;
    8   using   System.Data.Entity.Infrastructure;
    9  
  10   using   Microsoft.Practices.ServiceLocation;
   11  
  12   using   Happy.Domain;
   13   using   Happy.DesignByContract;
   14  
  15   namespace   Happy.EntityFramework
   16   {
   17       ///   <summary> 
  18       ///   基于EntityFramework的工作单元。
   19       ///   </summary> 
  20       public   abstract   class   UnitOfWork : DbContext, IUnitOfWork
   21       {
   22           private   readonly  Dictionary<Type, IRepository> repositories =  new  Dictionary<Type, IRepository> ();
   23  
  24           ///   <summary> 
  25           ///   构造方法。
   26           ///   </summary> 
  27           protected   UnitOfWork()
   28           {
   29           }
   30  
  31           ///   <summary> 
  32           ///   构造方法。
   33           ///   </summary> 
  34           protected  UnitOfWork( string   nameOrConnectionString)
   35              :  base  (nameOrConnectionString)
   36           {
   37           }
   38  
  39           ///   <inheritdoc /> 
  40           public   bool  Contains<TAggregateRoot> (TAggregateRoot item)
   41               where   TAggregateRoot : AggregateRoot
   42           {
   43              item.MustNotNull( "  item  "  );
   44  
  45               return   this .Entry(item).State !=  EntityState.Detached;
   46           }
   47  
  48           ///   <inheritdoc /> 
  49           public   void  Save<TAggregateRoot> (TAggregateRoot item)
   50               where   TAggregateRoot : AggregateRoot
   51           {
   52              item.MustNotNull( "  item  "  );
   53  
  54               this .Set<TAggregateRoot> ().Add(item);
   55           }
   56  
  57           ///   <inheritdoc /> 
  58           public   void  Update<TAggregateRoot> (TAggregateRoot item)
   59               where   TAggregateRoot : AggregateRoot
   60           {
   61              item.MustNotNull( "  item  "  );
   62  
  63               this .Entry(item).State =  EntityState.Modified;
   64           }
   65  
  66           ///   <inheritdoc /> 
  67           public   void  Persist<TAggregateRoot> (TAggregateRoot item)
   68               where   TAggregateRoot : AggregateRoot
   69           {
   70              item.MustNotNull( "  item  "  );
   71  
  72               this .Entry(item).State =  EntityState.Unchanged;
   73           }
   74  
  75           ///   <inheritdoc /> 
  76           public   void  Delete<TAggregateRoot> (TAggregateRoot item)
   77               where   TAggregateRoot : AggregateRoot
   78           {
   79              item.MustNotNull( "  item  "  );
   80  
  81               this .Entry(item).State =  EntityState.Deleted;
   82           }
   83  
  84           ///   <inheritdoc /> 
  85           public   void  Merge<TAggregateRoot> (TAggregateRoot item)
   86               where   TAggregateRoot : AggregateRoot
   87           {
   88              item.MustNotNull( "  item  "  );
   89  
  90               var  persistItem =  this .Set<TAggregateRoot> ().Find(item.Id);
   91  
  92               this  .Entry(persistItem).CurrentValues.SetValues(item);
   93           }
   94  
  95           ///   <inheritdoc /> 
  96           public   void  Evict<TAggregateRoot> (TAggregateRoot item)
   97               where   TAggregateRoot : AggregateRoot
   98           {
   99              item.MustNotNull( "  item  "  );
  100  
 101               this .Entry(item).State =  EntityState.Detached;
  102           }
  103  
 104           ///   <inheritdoc /> 
 105           public   void   Flush()
  106           {
  107               try 
 108               {
  109                   base  .SaveChanges();
  110               }
  111               catch   (DbUpdateConcurrencyException ex)
  112               {
  113                   throw   new   OptimisticConcurrencyException(ex.Message, ex);
  114               }
  115           }
  116  
 117           public  TAggregateRoot Load<TAggregateRoot> (Guid id)
  118               where   TAggregateRoot : AggregateRoot
  119           {
  120               return   this .Set<TAggregateRoot> ().Find(id);
  121           }
  122  
 123           public   void  Refresh<TAggregateRoot> (TAggregateRoot item)
  124               where   TAggregateRoot : AggregateRoot
  125           {
  126              item.MustNotNull( "  item  "  );
  127  
 128               this  .Entry(item).Reload();
  129           }
  130  
 131           ///   <inheritdoc /> 
 132           public   void   Clear()
  133           {
  134               base  .ChangeTracker.Entries()
  135                                 .ToList()
  136                                .ForEach(entry => entry.State =  System.Data.EntityState.Detached);
  137           }
  138  
 139           ///   <inheritdoc /> 
 140           public  TRepository GetRepository<TRepository> ()
  141               where   TRepository : IRepository
  142           {
  143               var  key =  typeof  (TRepository);
  144  
 145               if  (! repositories.ContainsKey(key))
  146               {
  147                   var  repository = ServiceLocator.Current.GetInstance<TRepository> ();
  148                  (repository  as  IEntityFrameworkRepository).Owner =  this  ;
  149                  repositories[key] =  repository;
  150               }
  151  
 152               return   (TRepository)repositories[key];
  153           }
  154       }
  155  }

备注

其实我们经常忽略一个关于接口的问题,就是异常本身也是API的一部分,虽然这部分在C#中没有办法显式的表达,等我的朋友实现完了NH版本的工作单元的开发,我们就继续对异常进行抽象。

作者: Leo_wl

    

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

    

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

版权信息

查看更多关于准备抽象NHibernate和EntityFramework的详细内容...

  阅读:39次