如何将多个业务交易包装在另一个交易下?
How can I wrap multiple business transactions under another transaction?
在我的项目中,单个服务方法就是一个业务事务。例如,假设我有以下 Service/Repository:
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;
}
}
}
}
}
这是两个不同的东西,所以他们有自己的方法。然而,有时但不是全部,它们都是必需的并且需要是原子的。我试图创建一个新的服务方法,将它们包装在一个事务中,但它不会回滚数据库创建。
我还能如何使用相同的通用设计模式实现此目的 - 或者在这种情况下这不是一个好的模式 - 每个业务交易一个上下文?
您需要使这两种方法共享相同的数据库连接和事务。怎么做是你的选择。
您的代码看起来像反模式。您应该为每个工作单元使用一个 ObjectContext,其中 UOW 范围应包含您需要做的所有事情。通常,范围是 HTTP 请求。
如果你这样做,问题就会消失。但你也可以用任何你喜欢的方式解决它,只要你共享相同的连接和事务。
考虑使用 TransactionScope
将事务语义与其余部分分开。小心 - 您仍然需要共享一个连接,否则您将升级为分布式事务。
在我的项目中,单个服务方法就是一个业务事务。例如,假设我有以下 Service/Repository:
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;
}
}
}
}
}
这是两个不同的东西,所以他们有自己的方法。然而,有时但不是全部,它们都是必需的并且需要是原子的。我试图创建一个新的服务方法,将它们包装在一个事务中,但它不会回滚数据库创建。
我还能如何使用相同的通用设计模式实现此目的 - 或者在这种情况下这不是一个好的模式 - 每个业务交易一个上下文?
您需要使这两种方法共享相同的数据库连接和事务。怎么做是你的选择。
您的代码看起来像反模式。您应该为每个工作单元使用一个 ObjectContext,其中 UOW 范围应包含您需要做的所有事情。通常,范围是 HTTP 请求。
如果你这样做,问题就会消失。但你也可以用任何你喜欢的方式解决它,只要你共享相同的连接和事务。
考虑使用 TransactionScope
将事务语义与其余部分分开。小心 - 您仍然需要共享一个连接,否则您将升级为分布式事务。