我编写了一个不公开公共Commit()
方法的UnitOfWork实现。相反,UnitOfWork实现IDisposable
,并且在Dispose()
方法中执行Commit。我没有看到任何直接的问题,但它似乎是非正统的,所以我想知道你们是否可以指出一些不这样做的主要原因,我忽略了。
以下是一些示例代码:
public class DataService
{
public DataService()
{
_db = new MyDataContext();
_exceptionHandler = new SqlExceptionHandler();
}
private readonly MyDataContext _db;
private readonly SqlExceptionHandler _exceptionHandler;
public void Add(Product product, Cart cart)
{
using(UnitOfWork unitOfWork = new UnitOfWork(_db, ex=>_exceptionHandler.Handle(ex)))
{
unitOfWork.Create<CartItem>(new CartItem{CartId = cart.Id, ProductId = product.Id});
unitOfWork.Update<Product>(x => x.Id == product.Id, product => { product.OrderCount++; });
}
}
}
public class UnitOfWork : IDisposable
{
private readonly DataContext _dataContext;
private readonly Func<Exception, bool> _handleException;
private bool _dirty;
public UnitOfWork(DataContext dataContext, Func<Exception,bool> handleException)
{
_dataContext = dataContext;
_handleException = handleException;
}
private Table<T> Table<T>()
where T: class
{
return _dataContext.GetTable<T>();
}
private T[] Find<T>(Expression<Func<T,bool>> select)
where T: class
{
return Table<T>().Where(select).ToArray();
}
public void Create<T>(T persistentObject)
where T: class
{
Table<T>().InsertOnSubmit(persistentObject);
_dirty = true;
}
public void Update<T>(Expression<Func<T, bool>> select, Action<T> update)
where T : class
{
var items = Find<T>(select);
if (items.Length > 0)
{
foreach (var target in items) update(target);
_dirty = true;
}
}
public void Delete<T>(Expression<Func<T, bool>> select)
where T : class
{
var items = Find<T>(select);
switch (items.Length)
{
case 0: return;
case 1:
Table<T>().DeleteOnSubmit(items[0]);
break;
default:
Table<T>().DeleteAllOnSubmit(items);
break;
}
_dirty = true;
}
public void Dispose()
{
if (_dirty)
{
Commit(1);
}
}
private void Commit(int attempt)
{
try
{
_dataContext.SubmitChanges();
}
catch (Exception exception)
{
if (attempt == 1 && _handleException != null && _handleException(exception))
{
Commit(2);
}
else
{
throw;
}
}
}
}
答案 0 :(得分:5)
因为未处理的异常将提交事务。并且一个例外意味着某些事情没有按计划进行=交易不应该被提交。
如果在处置之前未调用Rollback
,则Dispose
中的Commit
要好得多。
答案 1 :(得分:0)
如果您在using
块中调用的某个函数抛出异常怎么办?它可能会使您的工作单元处于不一致/不完整的状态,然后您提交。