在EF变更跟踪器中加载行或不在实体框架中加载行时,如何更新实体所需的行?

人气:945 发布:2022-10-16 标签: asp.net dbcontext asp.net-core entity-framework-core

问题描述

我已经检查了该问题的所有方面,但没有一个对我有效。每个人都建议使用AsNoTracking()来解决该问题,但这对我的问题没有任何意义,因为我没有更新我从数据库调用的数据。

我有公司档案更新模式,该公司可以有或没有档案照片,但无论哪种方式,我都需要更新这些信息。这就是为什么我需要控制是创建一张照片还是更新一张照片。下面让我向您展示我的代码:

#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
如您所见,使用AsNoTracking()调用该数据在我的情况下毫无意义。我仅在该操作中收到该错误,所以其他FileRepo操作工作正常。

这是我的FileUploadToDatabase()方法:

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

这就是我的FileRepo类:

   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
    }

这是我的UnitOfWork:

这是我的存储库:

这是对我的更新模态的查询:

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

推荐答案

要更新文件结果,您正在使用DbSet.Update-它正在尝试将实体附加到ChangeTracker。如果已有具有相同密钥的附加对象,则附加将失败。

将您的存储库更改为以下内容。如果实体不在ChangeTracker中,它将更新所有字段,否则它将仅更正所需的属性:

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

更新

如果泛型存储库不知道Id属性,您可以为该属性定义接口:

public interface IEntityWithId 
{ 
   int Id {get;}
}
确保您的类是IEntityWithId的实现。然后更正存储库定义:

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

176