Quantcast
Channel: ASP.NET Core
Viewing all articles
Browse latest Browse all 9386

Problem with batch updating for master-details entities.

$
0
0

Hi

I have a master-detail view with 2 tables :

DefaultVisitProductHeaders -> Master table
DefaultVisitProductDetails -> Detail table

In my view, i've using ajax request to give end-user to add/update/remove details, then save them in tempData (not in _dbContext). Here is my master-detail view (for edit mode):

@model DefaultVisitProductHeaders<h4>Edit Drugs Package</h4><hr /><div class="row"><div class="col-md-6">        <form id="frmEditPackageHeaderItem" asp-action="Update" method="post"><div asp-validation-summary="All" class="text-danger"></div><input type="hidden" id="hdnDefaultVisitProductHeaderRowID" asp-for="DefaultVisitProductHeaderRowID" value="@Model.DefaultVisitProductHeaderRowID" /><div class="form-group"><label asp-for="DefaultVisitProductHeaderName" class="control-label"></label><input asp-for="DefaultVisitProductHeaderName" class="form-control" value="@Model.DefaultVisitProductHeaderName" /><span asp-validation-for="DefaultVisitProductHeaderName" class="text-danger"></span></div><br /><h4>Package Details List</h4><hr /><div id="divPackageDetails" class="container">
                @Html.RenderAction("GetPackageDetails", "Package", new { id = Model.DefaultVisitProductHeaderRowID })</div><div class="text-right"><button type="submit" id="btnUpdate" class="btn btn-success">Save</button>
                @Html.ActionLink("Back", "Index", "Package")</div></form></div></div><div id="divPopup"></div>

@section Scripts{
    <script src="~/js/jquery.validate.min.js"></script><script src="~/js/jquery.validate.unobtrusive.min.js"></script>
}

My problem is that when, click on save button to update database, i'm facing this error (for added entities) :

InvalidOperationException: The instance of entity type 'DefaultVisitProductHeaders' cannot be tracked because another instance with the same key value for {'DefaultVisitProductHeaderRowID'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap<TKey>.ThrowIdentityConflict(InternalEntityEntry entry)

Here is my update action :

[HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Update([Bind("DefaultVisitProductHeaderRowID, DefaultVisitProductHeaderName")] DefaultVisitProductHeaders packageHeader)
        {
            if (this.ModelState.IsValid)
            {
                var curPackageHeader = _dbContext.DefaultVisitProductHeaders.Find(packageHeader.DefaultVisitProductHeaderRowID);
                curPackageHeader.DefaultVisitProductHeaderName = packageHeader.DefaultVisitProductHeaderName;
                this.AttachPackageDetailsToDbContext(curPackageHeader);
                _dbContext.SaveChanges();

                return RedirectToAction("Index", "Package");
            }

            return View("Edit", packageHeader);
        }

And here is my helper methods (AttachPackageDetailsToDbContext, GetPackageDetailsList) :

private void AttachPackageDetailsToDbContext(DefaultVisitProductHeaders packageHeader)
        {
            List<DefaultVisitProductDetails> lstPackageDetails = this.GetPackageDetailsList();

            List<DefaultVisitProductDetails> lstItemsAdded = lstPackageDetails.Where(d => d.IranHealthEntityState == IranHealthEntityState.Added).ToList();
            List<DefaultVisitProductDetails> lstItemsModified = lstPackageDetails.Where(d => d.IranHealthEntityState == IranHealthEntityState.Modified).ToList();
            List<DefaultVisitProductDetails> lstItemsDeleted = lstPackageDetails.Where(d => d.IranHealthEntityState == IranHealthEntityState.Deleted).ToList();
            foreach (DefaultVisitProductDetails detailItem in lstItemsAdded)
            {
                _dbContext.DefaultVisitProductDetails.Add(detailItem); // Cause error!!
            }

            foreach (DefaultVisitProductDetails detailItem in lstItemsModified)
                _dbContext.Entry(detailItem).State = Microsoft.EntityFrameworkCore.EntityState.Modified;

            foreach (DefaultVisitProductDetails detailItem in lstItemsDeleted)
                _dbContext.Entry(detailItem).State = Microsoft.EntityFrameworkCore.EntityState.Deleted;
        }


private List<DefaultVisitProductDetails> GetPackageDetailsList()
        {
            List<DefaultVisitProductDetails> lstResult = null;
            #region Getting lstPackageDetails from tempData, if does not exists, generate new list!

            var tmp = TempData.Peek("_lstPackageDetails");
            if (tmp != null)
            {
                lstResult = JsonConvert.DeserializeObject<List<DefaultVisitProductDetails>>(tmp.ToString(), new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
            }

            if (lstResult == null)
            {
                lstResult = new List<DefaultVisitProductDetails>();
            }

            #endregion

            return lstResult;
        }

Where is my problem & how to solve it?
Thanks in advance.


Viewing all articles
Browse latest Browse all 9386

Trending Articles