EF CF问题和现有的一对一关系

时间:2012-07-23 13:10:35

标签: asp.net-mvc entity-framework ef-code-first one-to-one

我正在使用EF Code First的现有数据库并使用modelBuilder进行配置。我有两个表,其中一个SESSION可以有一个SUBJECT,类是这样的:

public class SessionItem {
   [Key]
   public int SessionId { get;set; }
   // Other Values
   public int Subject_ID { get;set; }

   public virtual Subject Subject { get;set; }
}

public class SubjectItem {
   [Key]
   public int Subject_ID { get;set; }
   // Other Values

   public virtual SessionItem Session { get;set; }
}

然后modelBuilder代码是:

modelBuilder.Entity<SessionItem>().ToTable("tblTblSessions");
modelBuilder.Entity<Subject>().ToTable("tblTblSubjects");
modelBuilder.Entity<SessionItem>()
   .HasOptional<Subject>(u => u.Subject)                     
   .WithOptionalDependent(c => c.Session).Map(p => p.MapKey("Subject_ID"));

这首先失败,直到我从SessionItem类中删除了Subject_ID,然后我得到了错误:发生了关系多重性约束违规:EntityReference只能有一个相关对象,但查询返回了多个相关对象。这是一个不可恢复的错误。

知道我哪里出错了吗?

3 个答案:

答案 0 :(得分:2)

试试这个:

public class SessionItem 
{
   [Key]
   public int SessionId { get;set; }
   // Other Values
   [ForeignKey("Subject")]
   public int? Subject_ID { get;set; }

   [ForeignKey("Subject_ID")]    
   public virtual SubjectItem Subject { get;set; }
}

您需要使Subject_ID外键可以为空。

答案 1 :(得分:2)

实体框架不支持one-to-one foreign key associations,因为EF不知道唯一的键约束是什么(会话表中的Subject_ID列显然有)。

您必须通过将关系映射为一对多来解决此问题。按照@ flem对SessionItem实体的回答进行映射,对于SubjectItem实体,请完全删除public virtual SessionItem Session { get;set; }或将其替换为

public virtual ICollection<SessionItem> Sessions { get; set; }

对于此关系,您不再需要使用Fluent API进行映射,或者如果您需要,它应该是:

modelBuilder.Entity<SessionItem>()
    .HasOptional(se => se.Subject)                     
    .WithMany() // or WithMany(su => su.Sessions)
    .HasForeignKey(se => se.Subject_ID);

当您向该集合添加项目时,您必须在业务逻辑中确保不添加多个项目,因为您的数据库中不能有多个具有相同Subject_ID的行唯一键约束。从数据库(包括会话)加载主题时,会话集合为空或者只有一个元素,但不能更多。

答案 2 :(得分:1)

[Table("tblTblSessions")]
public class SessionItem {
    [Key]
    public int SessionId { get; set; }

    public virtual SubjectItem Subject { get; set; }
}

[Table("tblTblSubjects")]
public class SubjectItem {
    [Key, ForeignKey("Session")]
    public int Subject_ID { get; set; }

    public virtual SessionItem Session { get; set; }
}

SubjectItem和SessionItem之间的一对一关系,您可以摆脱所有的modelBuilder代码 - 您正在进行的所有表命名和一对一映射都使用上面的属性和属性。

编辑:修正了拼写错误并标记了一对一的从属方。