Linq-To-Sql的工作单元模式与事务范围?

时间:2010-12-16 20:59:51

标签: c# linq-to-sql design-patterns

我想模仿我的门户应用程序中使用Linq-2-Sql在DDD中广泛使用的Repository方法。到目前为止,我有这个:

     public class LinqToSqlDal<DC,T>: IDisposable, IRepository<T> 
        where T: LinqEntity, new(),
        where DC: DataContext, new() 
     {

              private DC unitOfWork = null;

              public LinqToSqlDal(string connectionString) 
              {
                   this.unitOfWork = Activator.CreateInstance(typeof(DC), connectionString) as DC; 
              }

               public LinqToSqlDal(string connectionString, DataLoadOptions loadOptions): this(connectionString) 
              {
                   this.unitOfWork.LoadOptions = loadOptions;
              }

              public virtual void SubmitChanges() { 
                 this.unitOfWork.SubmitChanges();
              }

              public virtual List<T> Get(Expression<Func<T,bool>> query) 
              {
                   return this.unitOfWork.GetTable<T>().Where(query);
              }

              public virtual void Delete(Expression<Funct<T, bool>> query) 
              {
                   this.unitOfWork.GetTable<T>().DeleteAllOnSubmit(this.unitOfWork.GetTable<T>().Where(query));
              }

              public virtual T GetByID<T>(Expression<Funct<T, bool>> query) 
              {
                     return this.unitOfWork.GetTable<T>().Where(query).SingleOrDefault();
              }

              public virtual object Add(T entity, string IDPropertyName) 
              {
                this.unitOfWork.GetTable<T>().InsertOnSubmit(entity);
                this.SubmitChanges();

                 var ID = (string.IsNullOrEmpty(IDPropertyName)) ? null : 
                    entity.GetType().GetProperty(IDPropertyName).GetValue(entity, null);

                   return ID;
              }

               public virtual void SubmitChanges() 
               {
                   this.unitOfWork.SubmitChanges();
               }

              public void Dispose() 
              {
                 this.unitOfWork.Dispose();
              }


     }

所以现在我可以将它与实体所属的任何Entity和DataContext一起使用。我的问题是 - 在这个小的存储库好处中传递或实例化TransactionScope吗?到目前为止,我只有一个DataContext但可以有多个继续,可以对当前设计做些什么来确保跨多个数据上下文的事务?

这是使用泛型包装上下文并让客户端处理它的好方法吗?

1 个答案:

答案 0 :(得分:3)

我肯定会创建某种集中但外部控制的交易控制。就个人而言,我赞成UnitOfWork,因为您可以将其设计为仅与存储库模型相关的抽象,而不是任何特定于实现的细节。

目前,您的工作单元是特定于实现的。您的开发人员知道名为unitOfWork的对象实际上是Linq2SQL的DataContext。知道这一点,他们可以完全绕过存储库并使用UnitOfWork进行数据库调用。他们这样做是一个坏主意,但他们可以建议需要更好地将具体细节封装在更好的摘要背后。

我会使UnitOfWork成为一个令牌类;令牌只是一个抽象占位符,它指的是原子操作集。在幕后,您可以使用UnitsOfWork来键入DataContexts的集合,并在每次通过调用方法将该令牌呈现给存储库时将Context用于特定的UnitOfWork(它将作为参数传递)。当外部代码丢弃UnitOfWork时,处理DataContext。像这样设计您的存储库意味着消费代码不需要任何实现细节的知识。如果您后来认为Linq2SQL不能满足您的需求而您想切换到NHibernate,则更改将在Repository边界处结束;无论UnitOfWork是引用DataContext还是ISession,您的消费代码都不会给出飞行翻转。