0

When I do a POST to a controller, I intermittently get threading errors - though a lot of the time everything will work perfectly. These are the most common two:

New transaction is not allowed because there are other threads running in the session.

The transaction operation cannot be performed because there are pending requests working on this transaction.

I have read multiple replies on why this happens. Such as this one and this one, but I can't say I understand. I know just posting code is horrible practice on SO, and I generally do my best to avoid it, but I really don't know what to ask past "Can you please take a look and let me know if you see any obvious problems."

// 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); } 

Note: I am 100% sure this has to do with async and is not MongoDb specific. The code below is equivalent of saving something to SQL with EF. I am sure the other Mongo bits are completely irrelevant to the question.

await mongoItems.FindOneAndUpdateAsync( Builders<BsonDocument>.Filter.Eq("_id", item.Id), update); 

db is our Entity Framework dbContext (just normal dbContext used with SQL, we have two databases - Mongo and SQL).

1 Answer 1

2

I don't see you creating your context in your method body. Entity framework contexts are not thread safe.

Sign up to request clarification or add additional context in comments.

3 Comments

:All our controllers inherit from a custom controller class (inheriting from API controller). This custom class defines 'db', which is our context (and inherits from dbContext). Should I instantiate another instance of dbContext in my method? Thank you for the reply btw.
It's generally a poor practice to instantiate a context in a controller base precisely for the problem you've run into. In general you want the shortest lifetime possible on your contexts.
Looks like this is the best answer I am going to get. Ty again - really glad at least someone replied. A lot of the time these vague questions get completely passed by.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.