TestInitialize上的集成测试中的多个上下文的一个事务

时间:2018-01-21 19:52:09

标签: entity-framework transactions integration-testing

我正在编写集成测试,我想使用事务范围。 我们使用EF和存储库与上下文。

如果我有一个Repository和一个Context,那么它看起来像这样:

[TestInitialize]
public void RuleEngineTestsStart() {
    customContext = new CustomContext();
    transaction = customContext.Database.BeginTransaction();
    repo = new CustomRepository(customContext);

    // I need to make this context to work in the same transaction as above
    anotherContext = new AnotherContext();
    anotherRepo = new AnotherRepository(anotherContext);
}

在测试结束时(TestCleanup)我想transaction.Rollback();一切。

我希望所有使用不同上下文的存储库拥有相同的事务,是否可能?如何创建事务并将其“发送”到所有三个上下文? 请不要对所有存储库使用一个上下文,但由于原因(我们希望以后每个上下文都有自己的DbSets在微服务中使用),这是不可能的。

修改 在评论中我被要求包含更多代码,但是,我认为没有必要回答我的问题。

customContext = new CustomContext();
repo = new CustomRepository(customContext);

customContext2 = new CustomContext2();
otherRepository = new CustomRepository2(customContext2);

// class to be tested needs both repositories
ToBeTestedClass cl = new ToBeTestedClass(customRepository, otherRepository);

// "BASE" interface
public interface IRepository<TEntity> where TEntity : class
{
    TEntity GetById(long id);
    IEnumerable<TEntity> GetByFilter(Expression<Func<TEntity, bool>> predicate);
    TEntity GetSingleByFilter(Expression<Func<TEntity, bool>> filter);
    void Insert(TEntity entity);
    void Delete(long id);
    void Update(TEntity entity);
    ...
}

 // BASE CLASS
 public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    protected readonly DbContext _context;
    protected readonly DbSet<TEntity> _dbSet;

    public Repository(ColldeskDbContext context)
    {
        _context = context;
        _dbSet = context.Set<TEntity>();
    }

    // GetSingle, GetAll, Insert, Update etc.

  }

  // CustomRepository (other Repositories are similar, with custom methods)
  public interface ICustomRepository : IRepository<CusotmData>
   {
         // some specific methods that are not in Base class   
   }

  public class CustomRepository: Repository<CustomData>, ICustomRepository
  {
    public CustomRepository(CustomContext context) : base(context)
    {
    }
    // custom methods that are specific for given context
  }

  // Contexts - each context consists of its one DbSets

2 个答案:

答案 0 :(得分:0)

请勿在您的存储库中使用dbContext.SaveChanges()。创建存储库时使用ONE dbContext。样品:

        using ( var db = new YourDbContext() )
        {
            // Create and begin transaction
            using ( var transaction = db.Database.BeginTransaction() )
            {
                try
                {
                    // ONE dbContext for all repositories
                    var firstRepo = new Custom1Repository(db);
                    var secondRepo = new Custom2Repository(db);

                    City city = new City { Description = "My city" };
                    Street street = new Street { Description = "My street", City = city};
                    firstRepo.Insert(city);
                    secondRepo.Insert(street);

                    // Save all your changes and after that commit transaction
                    db.SaveChanges();
                    transaction.Commit();
                }
                catch ( Exception ec)
                {
                    transaction.Rollback();
                }
            }
        }

这样做你的存储库就变成了DbSet<TEntity>

的包装器

答案 1 :(得分:0)

我已经发现我可以像这样简单地使用TransactionScope:

         private TransactionScope _scope;

        [TestInitialize]
        public void TestInitialize()
        {
            _scope = new TransactionScope();
        }

        [TestCleanup]
        public void TestCleanup()
        {
            _scope.Dispose();
        }

然后每个Context都将在此TransactionScope中运行。