How to update entity desipite the row is loaded in EF change tracker or not in entity framework?

Viewed 253

I allready look out everything of that problem but none of them worked for me.Everyone is suggestion to use AsNoTracking() for that problem but its has no sense with my problem because im not updating the data which i call from my database.

I have company profile update modal, this company can have profile photo or not but either way i need to update those informations. So that's why i need to control is comapny creating a photo or updating a photo. Let me show u to my code in the bellow :

#region /*UpdateCompanyProfile*/
[HttpPost]
public IActionResult UpdateCompanyProfile(Company company, List<IFormFile> files, int FileID)
{
    try
    {
        if (ModelState.IsValid)
        {
            company.ModifiedDate = DateTime.Now;
            _unitOfWorkC.RepositoryCompany.Update(company);
            int firstRequest = HttpContext.Response.StatusCode;
            if (firstRequest == 200)
            {
                _unitOfWorkC.Complete();
                if (files.Count != 0)
                {
                    var File = _fileUploader.FileUploadToDatabase(files);
                    var FileResult = File.Result;
                    FileResult.CompanyID = company.CompanyID;
                    if (FileID == 0)//That's the point where i control that file, is it gonna be update or create.
                    {
                        _unitOfWorkFR.RepositoryFileRepo.Create(FileResult);
                        int secondRequest1 = HttpContext.Response.StatusCode;
                        if (secondRequest1 == 200)
                        {
                            int tryCatch = _unitOfWorkFR.Complete();
                            if (tryCatch != 15)
                            {
                                TempData["JS"] = "showSuccess();";
                            }
                            else
                            {
                                TempData["JS"] = "showError();";
                            }
                        }
                    }
                    else
                    {
                        FileResult.FileID = FileID;
                        _unitOfWorkFR.RepositoryFileRepo.Update(FileResult); //That's the point where i get the error.
                        int secondRequest2 = HttpContext.Response.StatusCode;
                        if (secondRequest2 == 200)
                        {
                            int tryCatch2 = _unitOfWorkFR.Complete();
                            if (tryCatch2 != 15)
                            {
                                TempData["JS"] = "showSuccess();";
                            }
                            else
                            {
                                TempData["JS"] = "showError();";
                            }
                        }
                        else
                        {
                            TempData["JS"] = "showError();";
                        }
                    }
                }
                
            }
            else
            {
                TempData["Message"] = "?irket g?ncelleme i?leminiz ba?ar?s?z!";
                TempData["JS"] = "showError();";
                return RedirectToAction("CompanyProfile");
            }
        }
        else
        {
            TempData["Message"] = "G??ncellemek istedi?iniz veri hatal?!";
            TempData["JS"] = "showError();";
            return RedirectToAction("CompanyProfile");
        }
    }
    catch (Exception ex)
    {
        var log = _logging.Logging(ex.Message, "Exception/Hata", company.CompanyID.ToString(),
            "CompanyProfile/UpdateCompanyProfile", getCurrentUser(), getCurrentUserClaimRole());
        _unitOfWorkLog.RepositoryLog.Create(log);
        _unitOfWorkLog.Complete();
        //TempData["Message"] = ex.Message;
        //TempData["JS"] = "showError();";
        return RedirectToAction("CompanyProfile");
    }
}
#endregion

As u can see, calling that data with AsNoTracking() has no sense in my stuation. I'm only getting that error in that action,so other FileRepo actions are working well.

That's my FileUploadToDatabase() method :

        public async Task<FileRepo> FileUploadToDatabase(List<IFormFile> files)
        {
            foreach (var file in files)
            {
                var fileName = Path.GetFileNameWithoutExtension(file.FileName);
                var fileExtension = Path.GetExtension(file.FileName);
                _fileRepo = new FileRepo
                {
                    FileName = fileName,
                    FileExtension = fileExtension,
                    FileType = file.ContentType,
                    CreatedDate= DateTime.Now
                };
                using (var dataStream = new MemoryStream())
                {
                    await file.CopyToAsync(dataStream);
                    _fileRepo.FileData = dataStream.ToArray();
                }
            }
            return _fileRepo;
        }

And that's my FileRepo class :

   public class FileRepo : Base
    {
        [Key]
        public int FileID { get; set; }

        [Required(ErrorMessage = "Required Field !")]
        public string FileName { get; set; }

        [Required(ErrorMessage = "Required Field !")]
        public string FileType { get; set; }

        [Required(ErrorMessage = "Required Field !")]
        public string FileExtension { get; set; }

        public string FilePath { get; set; }
        public bool FilePhotoIsDefault { get; set; }
        public byte[] FileData { get; set; }
        public int? CompanyID { get; set; }
        public Company Company { get; set; }
        #endregion
    }

That's my UnitOfWork :

enter image description here

and This is my Repository :

enter image description here

enter image description here

This is the query for my Update Modal:

        public IEnumerable<Company> GetByIDForCompanyProfileCompany(int ID)
        {
            return TradeTurkDBContext.Companies.Where(x => x.CompanyID == ID)
               .Include(x => x.Addresses.Where(x => x.IsDeleted == null || x.IsDeleted == false))
               //
               .Include(x => x.Products.Where(x => x.IsDeleted == null || x.IsDeleted == false))
               .ThenInclude(x => x.FileRepos.Where(x => x.IsDeleted == null || x.IsDeleted == false)).AsSplitQuery()
               //
               .AsNoTrackingWithIdentityResolution().ToList();
        }
1 Answers

For updating FileResult you are using DbSet.Update - it is trying to attach entity to ChangeTracker. Attaching will fail if there is already attached object with the same key.

Change your repository to the following. It will update all fields if entity is not in ChangeTracker, otherwise it will correct only needed properties:

public void Update(T model)
{
    if (model == null)
        throw new ArgumentNullException(nameof(model));

    // I hope your generic repository knows Model Id property
    var entry = _context.ChangeTracker.Entries<T>().FirstOrDefault(e => e.Entity.Id == model.Id);

    if (entry == null)
    {
        // entity not tracked, so attach it
        _dbSet.Update(model);
    }
    else
    {
        // setting values from not tracked object
        if (!ReferenceEquals(model, entry.Entity))
            entry.CurrentValues.SetValues(model);
    }
}

UPDATE

If generic repository don't know about Id property, you can define interface for that:

public interface IEntityWithId 
{ 
   int Id {get;}
}

Make sure that your classes is implementation of IEntityWithId. Then correct Repository definition:

public interface IRepository<T> where T: class, IEntityWithId
{
   ...
}
Related