添加到聚合根时未保存子实体

当我保存更改时,一切看起来都很好。CaseWorkNote 实体已正确创建并添加到 workNotes 集合(案例实体的属性)。当 CurrentUnitOfWork 调用 DbContext->SaveChanges() 时,我看到我的实体在那里,状态为已添加。


最后什么都没有保存到数据库中。


我在我的代码中错过了什么或者我做错了什么?


下面是我的代码和带有跟踪实体的屏幕截图。


模型:


    public class Case : FullAuditedAggregateRoot<Guid>

    {

        [Required]

        public CaseType Type { get; set; }

        [Required]

        public string Subject { get; set; }

        public string Descripion { get; set; }

        //Aggregated entity

        private HashSet<CaseWorkNote> _workNotes;

        public IEnumerable<CaseWorkNote> WorkNotes => _workNotes?.ToList();

        //

        public CaseWorkNote AddNote(string text)

        {

            if (_workNotes is null)

            {

                _workNotes = new HashSet<CaseWorkNote>();

            }

            CaseWorkNote workNote = CaseWorkNote.Create(this, text);

            _workNotes.Add(workNote);

            return workNote;

        }

    }

    public class CaseWorkNote : FullAuditedEntity

    {

        [ForeignKey("CaseId")]

        [Required]

        public Case Case { get; private set; }    

        [Required]

        public string Text { get; set; }            

        private CaseWorkNote() : base() { }

        public static CaseWorkNote Create(Case kase, string text)

        {

            return new CaseWorkNote()

            {

                Case = kase,

                Text = text

            };

        }

    }



智慧大石
浏览 99回答 2
2回答

幕布斯7119047

问题是默认的EF Core属性访问方式导致的,ToList()调用这里public IEnumerable<CaseWorkNote> WorkNotes => _workNotes?.ToList();不确定您遵循的是哪种类型的方法,但您违反了简单的良好设计规则,即属性(尤其是集合类型)不应在每次获取时分配。不仅因为它效率低下,而且还允许像 EF Core 这样的“智能”客户端检测实际类型,并在加载相关数据List时尝试使用它来添加项目。实际上,对于这种类型的实现,他们正在添加到一个被丢弃的列表中,换句话说——无处可去。因此 EF Core 加载相关数据/导航属性修复不起作用,这也可能影响更改跟踪器并导致奇怪的行为。要解决 EF Core 问题,您应该将 EF Core 配置为直接使用支持字段。最简单的方法是在覆盖内全局设置它OnModelCreating:modelBuilder.UsePropertyAccessMode(PropertyAccessMode.Field);它也可以针对每个实体或每个实体属性进行设置,但我会建议以上内容,而且 EF Core 3.0 中的预期变化之一是默认使用支持字段。不管怎样,现在问题就解决了。不过,最好遵循良好做法。该_workNotes成员应使用初始化程序或在类构造函数中进行初始化,属性获取器应直接返回它。如果想法是阻止调用者通过强制转换结果来访问私有成员,那么还有其他方法可以阻止不克隆集合内容的方法。例如://Aggregated entityprivate readonly HashSet<CaseWorkNote> _workNotes = new HashSet<CaseWorkNote>();public IEnumerable<CaseWorkNote> WorkNotes => _workNotes.Select(e => e);//无论是否保留导航属性的当前实现,都必须让EF Core 直接使用支持字段。

慕村9548890

添加外键属性CaseId。还添加了Virtual关键字。public class CaseWorkNote : FullAuditedEntity&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; [ForeignKey("CaseId")]&nbsp; &nbsp; &nbsp; &nbsp; [Required]&nbsp; &nbsp; &nbsp; &nbsp; public virtual Case Case { get; private set; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; public virtual Guid CaseId { get; private set; }&nbsp; /* Added */&nbsp; &nbsp; &nbsp; &nbsp; [Required]&nbsp; &nbsp; &nbsp; &nbsp; public virtual string Text { get; set; }&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; private CaseWorkNote() : base() { }&nbsp; &nbsp; &nbsp; &nbsp; public static CaseWorkNote Create(Case kase, string text)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new CaseWorkNote()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Case = kase,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text = text&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP