如何在EF中的两个表之间创建两个一对一的关系?

时间:2016-02-01 11:51:39

标签: c# entity-framework

我有两个一对一关联的表。主表消息

public class Message
{
    [Key]
    public Guid Id {get; set;}
    //Other fields
    public virtual MessageContent MessageContent {get;set;}
}

相关表 MessageContent

public class MessageContent
{
    [Key]
    [ForeignKey]
    public Guid MessageId {get; set;}
    //Other fields
    public virtual Message Message {get;set;}
}

效果很好。但是我需要从 MessageContent Message 添加两个以上的关系:

public class MessageContent
{
    [Key]
    [ForeignKey]
    public Guid MessageId {get; set;}
    //Other fields
    public virtual Message Message {get;set;}

    public virtual Message Reason {get;set;}
    public Guid? ReasonId {get;set;}

    public virtual Message Report {get;set;}
    public Guid? ReportId {get;set;}
}

抛出异常。如何将两个关系从相关表添加到主表?

2 个答案:

答案 0 :(得分:1)

您现在没有为ReasonReport指定外键。您需要像这样更改MessageContent

public class MessageContent
{
[Key]
[ForeignKey("Message")]
public Guid MessageId {get; set;}
//Other fields
public virtual Message Message {get;set;}

[ForeignKey("Reason")]
public Guid? ReasonId {get;set;}
public virtual Message Reason {get;set;}

[ForeignKey("Report")]
public Guid? ReportId {get;set;}
public virtual Message Report {get;set;}
}

或者你可以通过流利的api来做到这一点:

modelBuilder.Entity<MessageContent>()
            .HasOptional(m => m.Reason)
            .WithRequired(r => r.MessageContent)
            .HasForeignKey("ReportId");

修改:您收到的错误是因为MessageMessageContent之间存在循环引用。最简单的方法是使MessageId中的MessageContent可以为空,并为MessageContent创建另一个主键。这会使你的关系成为可选的。第二个解决方案是告诉EF流畅的api哪个模型是主体,哪个是依赖实体。现在MessageContentMessage都被视为委托人,当您致电SaveChanges()时,EF不知道要先插入/更新哪一个。

答案 1 :(得分:0)

您没有像使用MessageId那样使用ForeignKey属性注释ReasonId和ReportId参数。您是否尝试过指定该属性?

通常,您在这里依赖于“最小配置”,EF确定,例如,MessageId键与Message属性相关联,而不是Reason属性。虽然这可以起作用,但是它可能很难检测出错的时间或者你已经超越了EF可以推断的那条线。

通常,更明确可以提供帮助。例如:

  • 在ForeignKey
  • 上填写构造函数参数
  • 使用流畅配置完全指定属性,例如:克。

    builder.Entity().HasOptional(mc => mc.Reason)
        .WithMany()
        .HasForeignKey(mc => mc.ReasonId);