我想模仿我的门户应用程序中使用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但可以有多个继续,可以对当前设计做些什么来确保跨多个数据上下文的事务?
这是使用泛型包装上下文并让客户端处理它的好方法吗?
答案 0 :(得分:3)
我肯定会创建某种集中但外部控制的交易控制。就个人而言,我赞成UnitOfWork,因为您可以将其设计为仅与存储库模型相关的抽象,而不是任何特定于实现的细节。
目前,您的工作单元是特定于实现的。您的开发人员知道名为unitOfWork的对象实际上是Linq2SQL的DataContext。知道这一点,他们可以完全绕过存储库并使用UnitOfWork进行数据库调用。他们这样做是一个坏主意,但他们可以建议需要更好地将具体细节封装在更好的摘要背后。
我会使UnitOfWork成为一个令牌类;令牌只是一个抽象占位符,它指的是原子操作集。在幕后,您可以使用UnitsOfWork来键入DataContexts的集合,并在每次通过调用方法将该令牌呈现给存储库时将Context用于特定的UnitOfWork(它将作为参数传递)。当外部代码丢弃UnitOfWork时,处理DataContext。像这样设计您的存储库意味着消费代码不需要任何实现细节的知识。如果您后来认为Linq2SQL不能满足您的需求而您想切换到NHibernate,则更改将在Repository边界处结束;无论UnitOfWork是引用DataContext还是ISession,您的消费代码都不会给出飞行翻转。