我在stackoverflow上搜索了一下,但没有找到类似的问题,请告诉我是否已经有这样的问题。
我试图实现一个通用的可重用存储库,具有同步和异步操作,但是由于我对Entity Framework和Unit Of Work的了解很少,所以我很难找到正确的实现方式。
我已经添加了一些SaveAndCommit操作的变化,但不知道使用事务和异步操作的最佳方法。
----编辑----
据我理解,当执行多个操作时应该使用事务,但为了理解的目的,我将其用于一个操作。(如果我错了,请纠正我)
这是我目前所做的。
public class Service<TEntity> : IService<TEntity>
where TEntity : Entity
{
#region Constructor and Properties
UnitOfWork _unitOfWork { get { return UnitOfWork.UnitOfWorkPerHttpRequest; } }
protected DbSet<TEntity> Entities
{
get { return _unitOfWork.Set<TEntity>(); }
}
#endregion Constructor and Properties
#region Operations
public virtual IQueryable<TEntity> QueryableEntities()
{
return Entities;
}
public virtual async Task<IList<TEntity>> WhereAsync(Expression<Func<TEntity, bool>> predicate)
{
return await Entities.Where(predicate).ToListAsync();
}
public virtual IList<TEntity> Where(Expression<Func<TEntity, bool>> predicate)
{
return Entities.Where(predicate).ToList();
}
public virtual async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
{
return await Entities.FirstOrDefaultAsync(predicate);
}
public virtual TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return Entities.FirstOrDefault(predicate);
}
public virtual async Task<TEntity> GetByIdAsync(int id)
{
return await Entities.FindAsync(id);
}
public virtual TEntity GetById(int id)
{
return Entities.Find(id);
}
// Method to the change the EntityState
public virtual void Save(TEntity entity)
{
if (entity.Id == 0)
{
Entities.Add(entity);
}
else
{
_unitOfWork.Entry(entity).State = EntityState.Modified;
}
}
#region Need clarification here
// Uses transaction scope to commit the entity and dispose automatically
// call rollback but this is not async and don't have any async
// functions (Or I could not find)
public virtual void SaveAndCommit(TEntity entity)
{
using (var transaction = _unitOfWork.BeginTransaction())
{
try
{
Save(entity);
transaction.Commit();
}
catch (DbEntityValidationException e)
{
}
}
}
// This is asynchronous but don't uses transaction
public virtual async Task SaveAndCommitAsync(TEntity entity)
{
try
{
Save(entity);
await _unitOfWork.SaveChangesAsync();
}
catch (DbEntityValidationException e)
{
}
}
// Tried to mix async and transaction but don't know if it will actually
// work or correct way of doing this
public virtual async Task SaveAndCommitWithTransactionAsync(TEntity entity)
{
using (var transaction = _unitOfWork.BeginTransaction())
{
try
{
Save(entity);
await _unitOfWork.SaveChangesAsync();
}
catch (DbEntityValidationException e)
{
transaction.Rollback();
}
}
}
#endregion Need clarification here
public virtual async Task DeleteAsync(TEntity entity)
{
if (entity == null) return;
Entities.Remove(entity);
await _unitOfWork.SaveChangesAsync();
}
//All similar methods for delete as for Save
public virtual async Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate = null)
{
if (predicate != null)
{
return await Entities.CountAsync(predicate);
}
return await Entities.CountAsync();
}
#endregion Operations
}
请指导我并建议最佳实现方法。
现在,似乎使用异步调用实现事务范围的正确方法是
public virtual async Task SaveAndCommitWithTransactionAsync(TEntity entity)
{
using (var transaction = _unitOfWork.BeginTransaction())
{
Save(entity);
await _unitOfWork.SaveChangesAsync();
// Still no changes made to database
transaction.Commit();
//Rollback will automatically be called by using in dispose method
}
}
参考资料 MSDN 参考文献
visualstudiomagazine.com 对于:当您调用 SaveChanges 时,只有在调用 Transaction 对象的 Commit 方法后,您的更改才会生效。