在我的项目中,单个服务方法是业务事务。例如,假设我有以下服务/存储库:
public interface IDocumentService {
void CreateDocument(Document doc);
void AttachFileToDocument(int documentId, string filepath);
}
public class DocumentService
{
private readonly IDocumentRepository _repository;
public DocumentService(IDocumentRepository repository)
{
_repository = repository;
}
public void CreateDocument(Document doc)
{
// do some validation
// ..
// create entity object....direct mapping, automapper, whatever
DocEntity entity = new DocEntity()
entity.Name = doc.Name;
// etc
using (var db = new DbEntities())
{
_repository.Insert(db, doc);
_repository.AddSource(db, entity, doc.Sheet.SourceId);
db.SaveChanges();
}
}
public void AttachFileToDocument(int documentId, string filepath)
{
using (var context = new DbEntities())
{
DocEntity doc = _repository.GetById(context, id);
// validation etc
using (var tran = context.Database.BeginTransaction())
{
try
{
// ..
// determine filename
// copy file
// update pointer to file in doc database
// ..
// save changes
context.SaveChanges();
tran.Commit();
}
catch (System.Exception)
{
tran.Rollback();
throw;
}
}
}
}
}
这是两个不同的东西,所以他们得到了自己的方法。但是,有时但不是全部,它们都是必需的,需要是原子的。我试图创建一个新的服务方法,在事务中包装它们,但它不会回滚db create。
我如何使用相同的通用设计模式实现这一目标 - 或者在这种情况下这不是一个好的模式 - 每个业务事务一个上下文?
答案 0 :(得分:0)
您需要使两个方法共享相同的数据库连接和事务。你如何做到这一点是你的选择。
您的代码看起来像反模式。您应该在每个工作单元使用一个ObjectContext,其中UOW范围应该包含您需要执行的所有操作。通常,范围是HTTP请求。
如果你这样做,问题就会消失。但是,只要您共享相同的连接和事务,您也可以以任何方式解决它。
考虑使用TransactionScope
将事务语义与其余语义分开。注意 - 您仍然需要共享一个连接,否则您将升级到分布式事务。