首页 > 解决方案 > 实体框架不只保存一个实体类型上的一个属性的更新

问题描述

我在 Visual Studio 2017 中使用 ASP.Net Core MVC 和 Entity Framework Core。

我们正在使用一个非常直接的存储库模式。

我已经进入这个项目八个月了,这是我第一次在这个实体上的这个属性上遇到这个奇怪的问题,在 UpdateChanges 之后保存到 SaveChanges 上的数据库中。

所以这里是流程。

1) 我有一个创建控制器操作来保存一个名为 Recommendation 的新实体。建议书有一个称为发现的父实体。当我创建新建议时,我必须更新父结果的状态。此外,Finding 实体有一个名为 Audit 的父实体。当我编辑结果状态时,我还必须更新审计状态。

这是一些代码。

[HttpPost]
public IActionResult Create(CreateIntRecommendationVM createIntRecommendationVM)
{
    int findingId = createIntRecommendationVM.Finding.FindingId;
        Finding finding = _findingRepo.Findings
            .Include(f => f.Audit)
            .Where(f => f.FindingId == findingId)
            .FirstOrDefault();

    if (RecModelStateIsValid(ModelState))
        {
            ClaimsPrincipal user = HttpContext.Request.HttpContext.User;
            short staffId = short.Parse(user.Claims.Single(c => c.Type == "StaffId").Value);

            Recommendation recommendation = createIntRecommendationVM.Recommendation;
            recommendation.RecFindingId = findingId;

            #region Get Recommendation Number
            recommendation.RecCd = GetRecommendationNumber(findingId);
            #endregion

            recommendation.RecStatusId = 10;
            recommendation.RecStaffId = staffId;
            recommendation.RecLastUpdateDt = DateTime.Now;

            _recommendationRepo.Add(recommendation);
            _recommendationRepo.SaveChanges();

            bool unresolvedFinding = false;
            bool unresolvedAudit = false;
            int? oldFindingStatus = finding.FindingStatusId;
            if (finding.FindingStatusId != 10)
            {
                finding.FindingStatusId = 10;
                unresolvedFinding = true;
            }
            if (oldFindingStatus != 10 && finding.Audit.StatusID != 10)
            {
                finding.Audit.StatusID = 10;
                unresolvedAudit = true;
            }

            _findingRepo.Update(finding);
            _findingRepo.SaveChanges();

当我在调试模式下运行并设置断点并在单步执行时进行检查时,我肯定将 find.FindingStatusId 设置为 10 并将 find.Audit.StatusID 设置为 10。

_findingRepo.Update(finding);

点击这个回购:

public class FindingRepository : IFindingRepository
    {
        private ApplicationDbContext context;
        public FindingRepository(ApplicationDbContext ctx)
        {
            context = ctx;
        }

        public IQueryable<Finding> Findings => context.Findings;

        public Finding Get(int id)
        {
            Finding finding = context.Findings.Find(id);
            return finding;
        }

        public void Add(Finding finding)
        {
            context.Findings.Add(finding);
        }

        public void Update(Finding finding)
        {
            context.Findings.Update(finding);
        }

        public void Delete(int id)
        {
            context.Database.ExecuteSqlCommand("sp_delete_finding_int @finding_id = {0}", id);
        }

        public void SaveChanges()
        {
            context.SaveChanges();
        }
    }

所以这是奇怪的部分。find.Audit.StatusID 正在数据库中更新。find.FindingStatusId 不是。

因此,对于实体,我发送到 repo 的 Update 方法的“发现”,正在更新的实体的“FindingStatusId”没有得到保存。但是,“finding”实体的父级“Audit”,“StatusID”正在被保存。

我一生都无法弄清楚这里发生了什么。

为了完整起见,我将发布 Find and Audit Entity Models。

[Table("finding")]
    public class Finding
    {
        private string _findingText;

        [Key]
        [Column("finding_id")]
        public int FindingId { get; set; }

        [Column("finding_audit_id")]
        public int FindingAuditId { get; set; }

        [Column("finding_cd")]
        [Display(Name = "Finding #")]
        [StringLength(15)]
        public string FindingCd { get; set; }

        [Column("finding_tx")]
        [Required(ErrorMessage = "Description Required")]
        [StringLength(7000)]
        public string FindingText
        {
            get
            {
                return _findingText;
            }
            set
            {
                _findingText = value?.Trim();
            }
        }

        [Column("finding_page_cd")]
        [StringLength(100)]
        public string FindingPageCd { get; set; }

        [Column("finding_joint_cd")]
        public string FindingJointCd { get; set; }

        [Column("finding_compliance_tx")]
        [StringLength(20)]
        public string FindingComplianceText { get; set; }

        [Column("finding_prior_year_cd")]
        [Display(Name = "Repeat Finding")]
        public string FindingPriorYearCd { get; set; }

        [Column("finding_decision_cd")]
        public string FindingDecisionCd { get; set; }

        [Column("finding_request_decision_cd")]
        public string FindingRequestDecisionCd { get; set; }

        [Column("finding_decision_ogc_concur_cd")]
        public string FindingDecisionOgcConcurCd { get; set; }

        [Column("finding_pdl_id")]
        public int? FindingPdlId { get; set; }

        [Display(Name = "Significant")]
        [Column("finding_significant_cd")]
        public string FindingSignificantCd { get; set; }

        [Column("finding_on_stay_cd")]
        public string FindingOnStayCd { get; set; }

        [Column("finding_stay_request_cd")]
        public string FindingStayRequestCd { get; set; }

        [Column("finding_last_update_dt")]
        public DateTime FindingLastUpdateDate { get; set; }

        [Column("finding_update_staff_id")]
        public short? FindingUpdateStaffId { get; set; }

        [Column("finding_cd_org")]
        public string FindingCdOrg { get; set; }

        [NotMapped]
        public string RepeatingYearsDisplayList
        {
            get
            {
                if (RepeatingYears?.Count > 0)
                {
                    string repeatingYears = string.Empty;
                    RepeatingYears.ForEach(ry =>
                        repeatingYears += $"{ry.FindingFyCd}, ");
                    return repeatingYears.Remove(repeatingYears.Length - 2);
                }
                return string.Empty;
            }
        }

        #region Navigation Properties
        [Column("finding_finding_type_id")]
        public short? FindingTypeId { get; set; }
        [ForeignKey("FindingTypeId")]
        public FindingType FindingType { get; set; }

        [Column("finding_status_id")]
        public int? FindingStatusId { get; set; }
        [ForeignKey("FindingStatusId")]
        public Status FindingStatus { get; set; }

        public List<FindingFiscalYear> RepeatingYears { get; set; }
        public List<Recommendation> Recommendations { get; set; }

        [ForeignKey("FindingAuditId")]
        public Audit Audit { get; set; }
        #endregion
    }



[Table("audit")]
    public class Audit
    {
        private string _auditAcnCd;
        private string _title;
        private string _summary;

        [Key]
        [Column("audit_id")]
        public int AuditID { get; set; }

        [Required(ErrorMessage = "ACN Required")]
        [Display(Name="ACN:")]
        [Column("audit_acn_cd")]
        public string AuditAcnCd
        {
            get
            {
                return _auditAcnCd;
            }
            set
            {
                _auditAcnCd = value?.Trim();
            }
        }

        [Required(ErrorMessage = "Title Required")]
        [Display(Name = "Title:")]
        [Column("audit_report_title_tx")]
        public string Title
        {
            get
            {
                return _title;
            }
            set
            {
                _title = value?.Trim();
            }
        }

        [Required(ErrorMessage = "Issuer Required")]
        [Display(Name="Issuer:")]
        [Column("audit_issuer_tx")]
        public string Issuer { get; set; }

        [Display(Name = "Sensitive Designation")]
        [Column("audit_sensitive_cd")]
        public string AuditSensitiveCode { get; set; }

        [Display(Name = "Alternative Product")]
        [Column("audit_alternate_product_cd")]
        public string AuditAlternateProductCode { get; set; }

        [RegularExpression("([1-9][0-9]*)", ErrorMessage = "Priority must be a number.")]
        [Display(Name = "Priority:")]
        [Column("audit_priority_cd")]
        public short? Priority { get; set; }

        [StringLength(maximumLength: 1000,ErrorMessage = "Max Length: 1000")]
        [Display(Name = "Summary:")]
        [Column("audit_summary_tx")]
        public string Summary
        {
            get
            {
                return _summary;
            }
            set
            {
                _summary = value?.Trim();
            }
        }

        [Column("audit_gao_contact_tx")]
        [Display(Name = "GAO Contact:")]
        [StringLength(maximumLength: 200, ErrorMessage = "Max Length: 200")]
        public string AuditGaoContactText { get; set; }

        [Column("audit_gao_job_cd")]
        [Display(Name = "GAO Job Code:")]
        [StringLength(maximumLength: 200, ErrorMessage = "Max Length: 30")]
        public string AuditGaoJobCode { get; set; }

        [Display(Name = "Lead Office:")]
        [Column("audit_lead_office_id")]
        public short? LeadOfficeID { get; set; }

        #region Navigation Properties
        [Required(ErrorMessage = "Audit Type Required.")]
        [Display(Name = "Audit Type:")]
        [Column("audit_audit_type_id")]
        public short AuditTypeID { get; set; }
        [Display(Name = "Audit Type:")]
        public AuditType AuditType { get; set; }

        [Column("audit_status_id")]
        public int StatusID { get; set; } 
        public Status Status { get; set; }

        [Required(ErrorMessage = "Office is Required.")]
        [Display(Name = "Offices:")]
        [Column("audit_office_id")]
        public short? OfficeID { get; set; }
        public Office Office { get; set; }

        [ForeignKey("AuditID")]
        public External External { get; set; }

        public IEnumerable<AuditLog> AuditLogs { get; set; }
        public IEnumerable<Finding> Findings { get; set; }
        public IEnumerable<Assignment> Assignments { get; set; }

        [Column("audit_update_staff_id")]
        public short UpdateStaffID { get; set; }

        [Column("audit_oig_manager_id")]
        [Display(Name = "OIG Audit Manager:")]
        public short? OigAuditManagerId { get; set; }
        [Display(Name = "OIG Audit Manager:")]
        [ForeignKey("OigAuditManagerId")]
        public Staff OigAuditManager { get; set; }

        [Column("audit_fsa_office_id")]
        [Display(Name = "FSA Audit Lead:")]
        public int? FsaLeadOfficeId { get; set; }
        [Display(Name = "FSA Audit Lead:")]
        [ForeignKey("FsaLeadOfficeId")]
        public FSAOffice FsaLeadOffice { get; set; }

        [ForeignKey("LeadOfficeID")]
        public Office LeadOffice { get; set; }
        #endregion
    }

标签: entity-framework-coreasp.net-core-mvc-2.0

解决方案


好吧,就像我希望今天早上重新打开它一样,重新开始,它正在工作。

伊万,我相信你是对的。您无需为实体框架调用更新。如果我忘记了 Update 语句,我之前已经注意到了这一点。

如果你不需要,你会无缘无故地在 repo 中进行更新。

我在数据库中手动重置场景以一遍又一遍地测试它。一定有什么东西已经腐败了。

但是,如果上面的所有代码对任何人都有帮助,它都可以正常工作。


推荐阅读