DbContextTransaction and Multi-thread: The connection is already in a transaction and cannot participate in another transaction
当我尝试使用多个线程调用同一方法时遇到此错误:连接已在一个事务中,不能参与另一个事务。 EntityClient不支持并行事务。
而且我发现我的问题在某种程度上类似于此:Entity Framework中的SqlException-不允许新事务,因为会话中正在运行其他线程
我的情况:
我有一个由多个主题实例化的类,每个线程-新实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public MarketLogic() { var dbContext = new FinancialContext(); AccountBalanceRepository = new AccountBalanceRepository(dbContext); CompositeTradeRepository = new CompositeTradeRepository( new OrderRepository(dbContext) , new PositionRepository(dbContext) , new TradeRepository(dbContext)); CompositeRepository = new CompositeRepository( new LookupValueRepository(dbContext) , new SecurityRepository(dbContext) , new TransactionRepository(dbContext) , new FinancialMarketRepository(dbContext) , new FinancialMarketSessionRepository(dbContext) ); } |
在MarketLogic类中,SavePosition()用于使用Entity Framework DbContext将信息保存到数据库中。 (SaveChanges())方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | private void SavePosition() { using (DbContextTransaction transaction = CompositeTradeRepository.OrderRepository.DbContext.Database.BeginTransaction()) { try { // business logic code, **this take some times to complete**. position = EntityExistsSpecification.Not().IsSatisfiedBy(position) ? CompositeTradeRepository.PositionRepository.Add(position) : CompositeTradeRepository.PositionRepository.Update(position); transaction.Commit(); } catch (Exception exception) { // some code transaction.Rollback(); } } } public Position Add(Position position) { // some code // context is a instance of FinancialContext, this class is generated by Entity Framework 6 context.SaveChanges(); } |
在我的场景中,当有2个线程并且更多尝试调用new MarketLogic()。SavePosition()时,发生了此问题。
我可以看到,虽然第一个事务尚未完成,但是第二个线程进入并开始了一个新事务。
但是我不明白为什么2个线程在不同的DbContext对象中,但是错误仍然发生
那怎么了?还是我错过了什么?
我的错,我将存储库保留为静态,因此所有线程共享相同的存储库,这意味着它们共享相同的DbContext,这在EF尚未完成允许更改以及对SaveChanges()的其他调用时引起了问题。 因此EF抛出异常。