3

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

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 不能有多个相关对象,但查询返回了多个相关对象。这是一个不可恢复的错误。

知道我哪里出错了吗?

4

3 回答 3

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 外键可以为空。

于 2012-07-23T13:50:38.353 回答
2

不幸的是,实体框架不支持一对一的外键关联,因为 EF 不知道唯一键约束是什么(您Subject_ID在 Session 表中的列显然具有)。

您必须通过将关系映射为一对多来解决此问题。按照@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由于唯一键约束,您的数据库中不能有多个相同的行。当您从包括会话在内的数据库中加载主题时,会话集合要么是空的,要么只有一个元素,但不会更多。

于 2012-07-23T14:39:04.977 回答
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 代码 - 您所做的所有表命名和一对一映射都由上面的属性和属性处理。

编辑:修正了一个错字并标记了一对一的依赖方。

于 2013-03-30T08:36:45.677 回答