实体框架事务期间与线程相关的多个错误
本文关键字:错误 线程 事务 框架 实体 | 更新日期: 2023-09-27 18:06:22
当我对控制器进行POST时,我间歇性地得到线程错误-尽管很多时候一切都将完美地工作。这是最常见的两种:
不允许新事务,因为会话中有其他线程正在运行。
事务操作无法执行,因为有挂起的请求正在处理此事务。
我读了很多关于为什么会发生这种情况的回复。比如这个和这个,但我不能说我理解。我知道仅仅在SO上发布代码是一种可怕的做法,我通常会尽我所能避免它,但我真的不知道该问过去什么;"你能看看吗?如果你看到任何明显的问题,请告诉我。"
// POST: api/CheckOuts
[AccessType(AccessType.Create)]
[HttpPost, Route("")]
[ResponseType(typeof(CheckOut))]
public async Task<IHttpActionResult> PostCheckOut(TransactionViewModel<CheckOut> tx)
{
//check if tx is a valid CheckOut Model Object
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
tx.Transaction.OrganizationId = SelectedOrganizationID;
tx.Transaction.OfficeId = SelectedOfficeID;
tx.Transaction.CheckedOutById = UserId;
tx.Transaction.Date = DateTime.UtcNow;
var items = tx.Transaction.Items.ToList();
long checkedOutStatus = db.Statuses.First( a => a.Name == "Checked Out" ).Id;
long checkedInStatus = db.Statuses.First( a => a.Name == "Checked In" ).Id;
//check item status
if( !items.TrueForAll( i=> i.StatusId == checkedInStatus ) )
{
return BadRequest("Not all items are in 'Checked In' state.");
}
var mongoItems = GetMongoCollection<BsonDocument>(MongoConstants.ItemsCollection);
items.ForEach(async item =>
{
var builder = Builders<BsonDocument>.Update;
var update = builder.Set("StatusId", checkedOutStatus)
.Set("CustodianId", tx.Transaction.TakenById)
.Set<BsonDocument, int?>("LocationId", null)
.Set<BsonDocument, string>("Location", null);
await mongoItems.FindOneAndUpdateAsync(
Builders<BsonDocument>.Filter.Eq("_id", item.Id),
update);
await AddItemHistory(item, UserId);
var primaryKeyOfTheItemId = db.ItemIds.Single(i => i.Item_Id == item.Id);
tx.Transaction.ItemIds.Add(primaryKeyOfTheItemId);
});
//add item
db.CheckOuts.Add(tx.Transaction);
await db.SaveChangesAsync(UserId);
return CreatedAtRoute("DefaultApi", new {controller = "checkouts", id = tx.Transaction.Id }, tx.Transaction);
}
注意:我100%肯定这与async
有关,而不是MongoDb特定的。下面的代码相当于用EF将一些东西保存为SQL。我确信Mongo的其他部分与这个问题完全无关。
await mongoItems.FindOneAndUpdateAsync(
Builders<BsonDocument>.Filter.Eq("_id", item.Id),
update);
db
是我们的实体框架dbContext(只是普通的dbContext与SQL一起使用,我们有两个数据库- Mongo和SQL)
我没有看到你在方法体中创建上下文。实体框架上下文不是线程安全的。