微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Entity Framework Core - 一对多,但父级也有单个子级的导航属性?

如何解决Entity Framework Core - 一对多,但父级也有单个子级的导航属性?

我目前在实体“对话”和“消息”之间建立了一对多的关系,其中一个对话可以包含多条消息。

这很好用:

public class Conversation
{
    public long ID { get; set; }
}

public class Message : IEntity
{
    public virtual Conversation Conversation { get; set; }
    public long ConversationID { get; set; }
    public long ID { get; set; }
}

但是,我正在尝试向名为“LastMessage”的“Conversation”类添加导航属性,该类将跟踪创建的最后一条消息记录:

public class Conversation
{
    public long ID { get; set; }
    public virtual Message LastMessage { get; set; }
    public long LastMessageID { get; set; }
}

当我尝试应用上述内容时,出现错误

system.invalidOperationException:子/依赖方无法 确定之间的一对一关系 “Conversation.LastMessage”和“Message.Conversation”。

如何维护“对话”和“消息”之间的一对多关系,但还要在“对话”类中添加导航属性以导航到单个“消息”记录?

解决方法

如果对话可以有多个消息,则称为一对多关系。 您必须修复表格:


public class Conversation
{
    [Key]
    public long ID { get; set; }
    [InverseProperty(nameof(Message.Conversation))]
    public virtual ICollection<Message> Messages { get; set; }
    
}

public class Message 
{
    [Key]
    public long ID { get; set; }

    public long ConversationID { get; set; }
 
    [ForeignKey(nameof(ConversionId))]
    [InverseProperty("Messages")]
    public virtual Conversation Conversation { get; set; }
      
 }
,

在尝试了各种数据注释和 Fluent API 废话之后,我能想到的最简洁的解决方案非常简单,两者都不需要。它只需要向 Conversation 类添加一个“私有”构造函数(如果您使用的是延迟加载,则为“受保护”构造函数),您的“DbContext”对象被注入到该类中。只需将您的“对话”和“消息”类设置为正常的一对多关系,并且现在可以从“对话”实体中获得数据库上下文,您可以让“最后一条消息”简单地从数据库返回一个查询使用 Find() 方法。 Find() 方法也使用了缓存,因此如果多次调用 getter,它只会访问一次数据库。

这是关于此能力的文档:https://docs.microsoft.com/en-us/ef/core/modeling/constructors#injecting-services

注意:“LastMessage”属性是只读的。要修改它,请设置“LastMessageID”属性。

class Conversation
{
    public Conversation() { }
    private MyDbContext Context { get; set; }
    // make the following constructor 'protected' if you're using Lazy Loading
    // if not,make it 'private'
    protected Conversation(MyDbContext Context) { this.Context = Context; }

    public int ID { get; set; }
    public int LastMessageID { get; set; }
    public Message LastMessage { get { return Context.Messages.Find(LastMessageID); } }
}

class Message
{
    public int ID { get; set; }
    public int ConversationID { get; set; }
    public virtual Conversation Conversation { get; set; }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。