【发布时间】:2018-12-12 04:07:19
【问题描述】:
我的查询比标题显示的要复杂一些。也许这是一个愚蠢的问题,但是我在网上搜索时找不到任何确定的答案。目前,我正在以自己的风格实现存储库/工作单元模式,它看起来有点像这样:
// Note: methods are async for conventions, not because
// they're truly async
public interface IUnitOfWork
{
Task Begin();
// The Task<int> is the numbers of rows affected by this commit
Task<int> Commit();
Task Rollback();
}
存储库或多或少可以这样表示:
public interface IWriteableRepository<T>
where T : class
{
EntityEntry<T> Insert(T item);
// Other CRUD methods removed for brevity; they're
// of similar signatures
}
这个想法是IUnitOfWork 将在内部保存一些TransactionScope 实例并处理相应的逻辑。
然后我有两个担忧。首先,如果每个IUnitOfWork 和IWriteableRepository<T> 实例都注入了DbContext 的不同实例(我暂时使用EntityFrameworkCore),那么在下面的代码中调用DbContext.BeginTransactionAsync() 会为两者生成一个事务范围吗?
await this.UnitOfWork.Begin();
this.Repository.Insert(someEntity);
var rows = await this.UnitOfWork.Commit();
换句话说,存储库是只对调用Begin()时创建的事务进行操作,还是完全独立操作?
我关心的第二个问题与实现IUnitOfWork 接口有关。到目前为止,我的方法大致是
public class UnitOfWork : IUnitOfWork
{
public UnitOfWork(DbContext context)
{
this.Context = context;
}
private DbContext Context { get; set; }
private TransactionScope Transaction { get; set; }
public async Task Begin()
{
if (this.Scope == null)
{
this.Transaction = await this.Context
.Database
.BeginTransactionAsync();
}
}
public async Task<int> Commit()
{
if (this.Scope != null)
{
var rows = await this.Context.SaveChangesAsync(false);
this.Scope.Commit();
this.Context.AcceptAllChanges();
return rows;
}
}
public Task Rollback()
{
if (this.Scope != null)
{
this.Scope.Rollback();
this.Scope.Dispose();
this.Scope = null;
}
return Task.CompletedTask;
}
}
我主要不确定Rollback() 方法是否可以改进。我觉得明确地处理对象是不正确的。我还有其他方法可以摆脱TransactionScope吗?
【问题讨论】:
-
如果您使用实体框架,我的诚实意见是您应该放弃存储库模式和工作单元,让您自己免于维护噩梦,将简单的逻辑隐藏在神秘的抽象层后面。 EF 已经为您实现了这些设计和模式。此外,如果您只想回滚数据库事务,请在 EF 中使用更现代的 TransactionBegin。除了将来必须重新设计之外,您的方法真的没有什么好处。
标签: c# entity-framework-core repository-pattern unit-of-work transactionscope