【问题标题】:How can I wrap multiple business transactions under another transaction?如何将多个业务事务包装在另一个事务下?
【发布时间】:2015-03-27 17:56:27
【问题描述】:

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

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。

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

【问题讨论】:

  • 我只想扩展 CreateDocument 方法。让它包含 0 个或多个文件。

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


【解决方案1】:

您需要使两种方法共享相同的数据库连接和事务。怎么做是你的选择。

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

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

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

【讨论】:

  • 因此,如果我理解正确,将上下文作为类级别变量注入服务并在应用程序层控制事务/保存(在我的情况下是与服务)。我不确定您所说的“使用 TransactionScope 将事务语义与其他语义分开”是什么意思,您能澄清一下您的意思吗?
  • 是的,完全正确。您可以忽略 TransactionScope 备注。它们对于这个问题并不重要。
  • 那么,事务不应该被视为“业务逻辑”的一部分吗?
  • 我不会这么说的。不过,您可以使用 TS 从更高层指示/注入事务行为。这很方便。
猜你喜欢
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多