如何在另一个交易下包装多个业务交易?

时间:2015-01-28 17:46:28

标签: c# transactions repository-pattern service-layer

在我的项目中,单个服务方法是业务事务。例如,假设我有以下服务/存储库:

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。

我如何使用相同的通用设计模式实现这一目标 - 或者在这种情况下这不是一个好的模式 - 每个业务事务一个上下文?

1 个答案:

答案 0 :(得分:0)

您需要使两个方法共享相同的数据库连接和事务。你如何做到这一点是你的选择。

您的代码看起来像反模式。您应该在每个工作单元使用一个ObjectContext,其中UOW范围应该包含您需要执行的所有操作。通常,范围是HTTP请求。

如果你这样做,问题就会消失。但是,只要您共享相同的连接和事务,您也可以以任何方式解决它。

考虑使用TransactionScope将事务语义与其余语义分开。注意 - 您仍然需要共享一个连接,否则您将升级到分布式事务。