A second operation started on this context before a previous operation completed. in .NET Core

55 Views Asked by At

My application appears to be encountering deadlock issues or shows an error

A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext

especially when multiple users are accessing different documents simultaneously.

To address this, we have implemented a mechanism where each user is assigned a specific document to work on, and we're maintaining this assignment in a document access table. When a document is loaded, we add an entry to this table, and when the user completes their work and submits the data, you remove the corresponding entry from the table.

It seems that the deadlock is occurring due to multiple operations on this document access table (CheckDocument is a table name) during concurrent user interactions.

Controller

This method will be called when users will click on Submit button.

[HttpPost("SaveDocumentAndParties")]
public ActionResult saveDocumentAndParties([FromBody] SaveDocumentParties sd)
{
        string jsondata = string.Empty;

        object lockObject = new object();
        bool lockAcquired = false;

        try
        {
            using (var dbContext = _dbContextFactory.CreateDbContext())
            {
                using (var transactionScope = new TransactionScope())
                {
                    // Trying to acquire the lock on the lockObject
                    lockAcquired = Monitor.TryEnter(lockObject);

                    dbContext.Database.GetDbConnection().ConnectionString = sd.ConnectionString;
                    var dbConString = dbContext.Database.GetDbConnection().ConnectionString;
                    dbContext.Database.GetDbConnection().ConnectionString = dbConString;

                    if (lockAcquired)
                    {
                        ImportCodedData getCodedData = dbContext.ImportCodedDatas.Where(x => x.Document_ID == sd.Document_ID).SingleOrDefault<ImportCodedData>();
                        ImportPage getImportData = dbContext.ImportPages.Where(x => x.Document_ID == sd.Document_ID).SingleOrDefault<ImportPage>();

                        if (getCodedData != null)
                        {
                            if (sd.UserTask == "Coder")
                            {
                                var qaCompleted = dbContext.ImportPages.Where(x => x.Document_ID == sd.Document_ID && x.Revision == 1 && x.Coded == 1).SingleOrDefault();

                                if (qaCompleted != null)
                                {
                                    jsondata = Newtonsoft.Json.JsonConvert.SerializeObject(
                                         new { Response = "QA already completed this document", Statuscode = StatusCodes.Status404NotFound });
                                }

                                AddTransaction1();
                                AddTransaction2();

                                CodedData objCode = new CodedData();
                                objCode.Document_ID = getImportData.Document_ID;
                                objCode.Image_File_Name = getImportData.Image_File_Name;
                                objCode.IsCorrected = sd.IsCorrected;
                                dbContext.CodedDatas.Add(objCode);
                            }
                            else
                            {
                                CodedData objCode = new CodedData();

                                objCode.Document_ID = getImportData.Document_ID;
                                objCode.Image_File_Name = getImportData.Image_File_Name;
                                dbContext.CodedDatas.Add(objCode);
                               
                                Transaction3();
                                Transaction4()
                            }
                        }

                        Transaction5()
                        }
                        else
                        {
                            ImportCodedData objcode = dbContext.ImportCodedDatas.Where(x => x.Document_ID == sd.Document_ID).Single<ImportCodedData>();

                            objcode.Document_Date = sd.Document_Date;
                            objcode.Estimated = sd.Estimated;
                            objcode.Document_Type = sd.Document_Type;
                            
                            dbContext.ImportCodedDatas.Update(objcode);
                        }
                        //geting details from parties master table
                        var getPartiesCount = dbContext.Parties.ToList();

                        // serializing data from in put json data
                        DeleteTransaction();

                        // inserting new data into Parties table

                        AddTransaction6();
                        AddTransaction7();

                        // inserting new data into Export_extras table
                        AddTransaction8();

                        if (sd.UserTask == "Coder")
                        {
                           ADDUPDTransaction();
                        }

                        ImportPage objImportPage = dbContext.ImportPages.Where(x => x.Document_ID == sd.Document_ID).Single<ImportPage>();
                        if (objImportPage != null)
                        {
                            //if (sd.UserRole == "CoderQA" && sd.UserTask == "Coder")
                            if (sd.UserTask == "Coder")
                            {
                                objImportPage.Coded = 1;
                                objImportPage.EnteredBy = sd.EnterBy;
                                objImportPage.DocType = sd.Document_Type;
                            }
                         
                            else if (sd.UserTask == "QA")
                            {
                                objImportPage.Revision = 1;
                                objImportPage.EnteredBy = sd.EnterBy;
                                //objImportPage.SetId = 1;
                            }

                            objImportPage.LastModified = System.DateTime.Now;

                            dbContext.ImportPages.Update(objImportPage);
                        }

                        // getting next document id
                        var docOrgID = objImportPage.Id + 1;

                        var nextDocumentId = "";
                        int nextId = 0;
                        bool isReturnFlag = false;
                        int codeCompletedCount = 0;
                        int qaCompletedCount = 0;
                        int totalDocCount = 0;

                        if (sd.UserTask == "QA")
                        {
                            CodingSession_Details[] cds = JsonConvert.DeserializeObject<CodingSession_Details[]>(sd.CodingSessionDetails);
                            if (!String.IsNullOrEmpty(sd.CodingSessionDetails))
                            {
                                if (sd.CodingSessionDetails != "null") //When coming from Unreviewed Review mode because coding session details is for 'All' Review mode
                                {
                                    if (sd.CodingSessionDetails.Length > 0)
                                    {
                                       // calling stored procedure
                                    }
                                }
                            }

                            totalDocCount = dbContext.ImportPages.Count();
                            qaCompletedCount = dbContext.ImportPages.Where(x => x.Coded == 1 && x.Revision == 1).Count();
                        }
                        else
                        {
                            codeCompletedCount = dbContext.ImportPages.Where(x => x.Coded == 1).Count();
                            totalDocCount = dbContext.ImportPages.Count();
                        }

                        //_codingdbContext.ImportPages.Where(x => x.Id == docOrgID).SingleOrDefault();
                        //var lstDocument = isReturnFlag==true?null:_codingdbContext.ImportPages.Where(x => x.Coded == 0).SingleOrDefault();
                        obj.Information("Document Saving Started..10051");
                        var lstDocument = dbContext.ImportPages.Where(x => x.Id == docOrgID).SingleOrDefault();

                        if (lstDocument == null)
                        {
                            /*Start : To Check Last Document*/
                            if (sd.UserTask == "Coder")
                            {
                                if (totalDocCount == codeCompletedCount)
                                {
                                    isReturnFlag = true;
                                }
                            }
                            else
                            {
                                if (totalDocCount == qaCompletedCount)
                                {
                                    isReturnFlag = true;
                                }
                            }
                            /*End*/
                        }
                        else
                        {
                            if (sd.isHistoryDocument != true)
                            {
                                var isAssignedSameDoc = dbContext.CheckDocuments.Where(p => p.Document_ID == lstDocument.Document_ID).FirstOrDefault();

                                if (isAssignedSameDoc == null)
                                {
                                    nextDocumentId = lstDocument.Document_ID;
                                    nextId = lstDocument.Id;
                                }
                                else
                                {
                                    var DocList = dbContext.CheckDocuments.Where(p => p.Document_ID == lstDocument.Document_ID && p.UserTask == sd.UserTask).ToList();
                                    if (DocList.Count > 0)
                                    {
                                        var checkDocsList = dbContext.CheckDocuments.Where(p => p.UserTask == sd.UserTask).Select(x => x.Document_ID).ToList();
                                        var listDocument = dbContext.ImportPages.Where(x => !checkDocsList.Contains(x.Document_ID)).Take(1).ToList();
                                        if (listDocument.Count > 0)
                                        {
                                            nextDocumentId = listDocument[0].Document_ID;
                                            nextId = listDocument[0].Id;
                                        }
                                    }

                                }
                            }
                            else
                            {
                                nextDocumentId = lstDocument.Document_ID;
                                nextId = lstDocument.Id;
                            }
                        }
                 
                        int result = dbContext.SaveChanges();

                        if (result > 0)
                        {
                            obj.Information("Document Saving Started..1717");
                            //Remove Document details from temp table
                            obj.Information("Before Update ");

                            // Acquire the lock
                            //Monitor.Enter(_lock);

                            if (sd.isHistoryDocument != true)
                            {
                                CheckDocument getDocDetails = dbContext.CheckDocuments.Where(x => x.Document_ID == sd.Document_ID && x.ProjectId == sd.ProjectId && x.UserTask == sd.UserTask && x.DocumentStatus == false).SingleOrDefault<CheckDocument>();
                                obj.Information("Update CheckDocuments : " + sd.Document_ID + ": " + sd.ProjectName + ": " + sd.UserTask);

                                if (getDocDetails != null)
                                {
                                    obj.Information("Removed Document from check table");
                                    //getDocDetails.DocumentStatus = true;
                                    //_codingdbContext.CheckDocuments.Update(getDocDetails);
                                    dbContext.CheckDocuments.Remove(getDocDetails);
                                    dbContext.SaveChanges();
                                }
                            }

                            // Release the lock
                            //Monitor.Exit(_lock);

                            obj.Information("Document Saving Started..100162");


                            //dbContextTransaction.Commit();

                            obj.Information("After update");
                            if (isReturnFlag)
                            {
                                jsondata = Newtonsoft.Json.JsonConvert.SerializeObject(new
                                {
                                    Response = "LastDocument",
                                    Message = "All the documents are completed."
                                });
                            }
                            else
                            {
                                jsondata = Newtonsoft.Json.JsonConvert.SerializeObject(new
                                {
                                    Response = "success",

                                    nextDocumentId = nextDocumentId,
                                    nextId = nextId,
                                    Message = "Document updated successfully"
                                });
                            }

                            // Commit the transaction if all operations succeed
                            transactionScope.Complete();
                            transactionScope.Dispose();

                            //return Ok(jsondata);

                        }
                        else
                        {
                            
                            if (isReturnFlag)
                            {
                                jsondata = Newtonsoft.Json.JsonConvert.SerializeObject(new
                                {
                                    Response = "LastDocument",
                                    Message = "All the documents are completed."
                                });
                            }
                            else
                            {
                                jsondata = Newtonsoft.Json.JsonConvert.SerializeObject(
                                    new { Response = "No documents to code", Statuscode = StatusCodes.Status404NotFound });
                            }

                            // Commit the transaction if all operations succeed
                            transactionScope.Complete();
                            transactionScope.Dispose();

                            //return Ok(jsondata);
                        }

                    }
                    else
                    {
                        obj.Information("Failed to acquire lock, another thread is holding it.");
                    }

                }
            }
        }
        catch (Exception ex)
        {
            
        }
        finally
        {
            // Always release the lock once done with the critical section
            if (lockAcquired)
            {
                Monitor.Exit(lockObject);
                obj.Information("Monitor Release s");
            }

        }

        return Ok(jsondata);
}

After clicking on next button now next available document will load and the below function is for that only

[HttpPost("GetImportedPath")]
public async Task<IActionResult> GetImportedPath([FromBody] ProjectTypes project)
{
        string jsondata = string.Empty;

        try
        {
            using (var dbContext = _dbContextFactory.CreateDbContext())
            {
                dbContext.Database.GetDbConnection().ConnectionString = project.ConnectionString;
                var dbConString = dbContext.Database.GetDbConnection().ConnectionString;
                dbContext.Database.GetDbConnection().ConnectionString = dbConString;

                //var dbContextTransaction = dbContext.Database.BeginTransaction();

                try
                {
                    try
                    {
                        /*Release Document first before loading new documents*/

                        var dbContextTransaction1 = dbContext.Database.BeginTransaction();
                        var lstcheckDocument = new CheckDocument();

                        object lockObject1 = new object();
                        bool lockAcquired1 = false;

                        // Trying to acquire the lock on the lockObject
                        lockAcquired1 = Monitor.TryEnter(lockObject1);

                        try
                        {
                            if (lockAcquired1)
                            {
                                lstcheckDocument = dbContext.CheckDocuments.Where(x => x.Document_ID == project.Document_ID && x.UserId == project.UserId && x.ProjectId == project.ProjectId && x.UserTask == project.UserTask && x.DocumentStatus == false).SingleOrDefault();
                                if (lstcheckDocument == null) { }
                                else
                                {
                                    //Remove Document details from temp table
                                    if (lstcheckDocument != null)
                                    {
                                        dbContext.CheckDocuments.Remove(lstcheckDocument);
                                        dbContext.SaveChanges();
                                    }

                                }
                            }
                            else
                            {
                                obj.Information("GetImportedPath - Loack Not Accquire");
                            }
                        }
                        catch (DbEntityValidationException e)
                        {
                            dbContextTransaction1.Rollback();
                            throw e;
                        }
                        finally
                        {
                            dbContextTransaction1.Commit();

                            //Release the lock
                            if (lockAcquired1)
                            {
                                obj.Information("Monitor Release");
                                Monitor.Exit(lockObject1);
                            }

                        }

                        var lstDocument = new List<ImportPage>();

                        if (project.IsEquiset == true)
                        {
                        }
                        else
                        {
                            #region Sequencial Loading

                            var _checkDocumentList = await dbContext.CheckDocuments.Where(p => p.ProjectId == project.ProjectId && p.UserTask == project.UserTask && p.DocumentStatus == false).Select(x => x.Document_ID).ToListAsync();
                            var _checkDocumentUser = await dbContext.CheckDocuments.Where(p => p.UserId == project.UserId && p.ProjectId == project.ProjectId && p.UserTask == project.UserTask && p.DocumentStatus == false).Select(x => x.UserId).ToListAsync();
                          
                            if (_checkDocumentList.Contains(project.Document_ID) && _checkDocumentUser.Contains(project.UserId))
                            {
                                if (project.UserTask == "Coder")
                                {
                                    lstDocument = await dbContext.ImportPages.Where(x => x.Coded == 0 && x.Document_ID == project.Document_ID).OrderBy(p => p.Document_ID).Take(1).ToListAsync();
                                }
                                if (project.UserTask == "QA")
                                {
                                    lstDocument = await dbContext.ImportPages.Where(x => x.Revision == 0 && x.Coded == 1 && x.Document_ID == project.Document_ID).OrderBy(p => p.Document_ID).ToListAsync();

                                    if (lstDocument.Count == 0)
                                    {
                                    }
                                   
                                }
                            }
                            else
                            {
                                if (project.UserTask == "Coder")
                                {
                                    lstDocument = await dbContext.ImportPages.Where(x => x.Coded == 0 && !_checkDocumentList.Contains(x.Document_ID)).OrderBy(p => p.Document_ID).Take(1).ToListAsync();
                                }
                                if (project.UserTask == "QA")
                                {
                                    lstDocument = await dbContext.ImportPages.Where(x => x.Revision == 0 && x.Coded == 1 && !_checkDocumentList.Contains(x.Document_ID)).OrderBy(p => p.Document_ID).ToListAsync();
                                  
                                }
                            }

                            if (lstDocument == null)
                            {
                            }
                            else
                            {
                                if (getPreviousDocId.Count == 0)
                                {
                                    if (project.UserTask == "Coder")
                                    {
                                        var documentCompleted = await dbContext.ImportPages.Where(x => x.Coded == 1).CountAsync();
                                        if (documentCompleted == lstDocumentCount)
                                        {
                                          
                                            //return Ok(jsondata);

                                        }

                                        if (lstDocument.Count == 0 && documentCompleted != lstDocumentCount)
                                        {
                                            if (project.UserTask == "Coder")
                                            {
                                                
                                            }

                                            //return Ok(jsondata);
                                        }

                                    }
                                    else if (project.UserTask == "QA")
                                    {
                                        var documentCompleted = await dbContext.ImportPages.Where(x => x.Coded == 1 && x.Revision == 1).CountAsync();
                                      //Some code


                                    }

                                }
                                else
                                {
                                    var dbContextTransaction2 = dbContext.Database.BeginTransaction();
                                    // Trying to acquire the lock on the lockObject

                                    object lockObject2 = new object();
                                    bool lockAcquired2 = false;

                                    lockAcquired2 = Monitor.TryEnter(lockObject2);

                                    try
                                    {
                                        if (lockAcquired2)
                                        {
                                            if (_checkDocumentList.Contains(project.Document_ID) && _checkDocumentUser.Contains(project.UserId))
                                            {

                                            }
                                            else
                                            {
                                                CheckDocument objDocuments = new CheckDocument();
                                                objDocuments.Document_ID = lstDocument[0].Document_ID;
                                                objDocuments.ProjectId = project.ProjectId;
                                                objDocuments.UserId = project.UserId;
                                                objDocuments.TimeStamp = longTimeStr;
                                                objDocuments.UserTask = project.UserTask;
                                                objDocuments.DocumentStatus = false;
                                                dbContext.CheckDocuments.Add(objDocuments);
                                                dbContext.SaveChanges();
                                            }
                                        }
                                        else
                                        {
                                            obj.Information("GetImportedPath - Lock Not Accuire when Adding");
                                        }
                                    }
                                    catch (DbEntityValidationException e)
                                    {
                                        dbContextTransaction2.Rollback();
                                        throw e;
                                    }
                                    catch (System.Data.Entity.Infrastructure.DbUpdateException e)
                                    {
                                        dbContextTransaction2.Rollback();
                                        throw e;
                                    }
                                    finally
                                    {
                                        dbContextTransaction2.Commit();

                                        if (lockAcquired2)
                                        {
                                            Monitor.Exit(lockObject2);
                                            obj.Information("Monitor Release 2");
                                        }
                                    }
                                }
                            }
                            #endregion
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }
        catch (Exception ex)
        {
        }

        return Ok(jsondata);
}
0

There are 0 best solutions below