同一实体类型代码的多个一对多关系优先
Posted
技术标签:
【中文标题】同一实体类型代码的多个一对多关系优先【英文标题】:Multiple one to many relations of the same entity type code first 【发布时间】:2014-02-19 15:57:31 【问题描述】:我在定义具有两个一对多关系(两个列表)的实体时遇到问题
public class Calendar
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public Guid ID get; set;
public virtual IList<Appointment> FreeSlots get; set;
public virtual IList<Appointment> AppointmentsList get; set;
...
public class Appointment
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int AppointmentID get; set;
public DateTime Start get; set;
public DateTime End get; set;
public String Type get; set;
public String Info get; set;
public Guid CalendarID get; set;
public virtual Calendar Calendar get; set;
代码优先代码:
modelBuilder.Entity<Appointment>().HasKey(u => new u.AppointmentID, u.CalendarID );
modelBuilder.Entity<Appointment>().HasRequired(u => u.Calendar).WithMany(c => c.FreeSlots).HasForeignKey(f => f.CalendarID).WillCascadeOnDelete(true);
modelBuilder.Entity<Appointment>().HasRequired(u => u.Calendar).WithMany(c => c.AppointmentsList).HasForeignKey(f => f.CalendarID).WillCascadeOnDelete(true);
约会有两个 PK,因为如果删除日历,我希望删除约会。
当我尝试向 FreeSlot 添加新约会时,我收到以下错误: 保存不为其关系公开外键属性的实体时发生错误。 EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。
我也尝试过这个映射,但没有成功:错误 0040:类型 Calendar_FreeSlots 未在命名空间 Project.DAL (Alias=Self) 中定义。
modelBuilder.Entity<Appointment>().HasKey(u => new u.AppointmentID, u.CalendarID );
modelBuilder.Entity<Calendar>().HasMany(c => c.FreeSlots).WithRequired(c => c.Calendar).HasForeignKey(c => c.CalendarID).WillCascadeOnDelete();
modelBuilder.Entity<Calendar>().HasMany(c => c.AppointmentsList).WithRequired(c => c.Calendar).HasForeignKey(c => c.CalendarID).WillCascadeOnDelete();
我想问题是我与同一类型的实体有两个一对多的关系,但我不知道正确的方法。
【问题讨论】:
【参考方案1】:您的映射中的错误是您对两个不同的关系使用了两次Appointment.Calendar
。那是不可能的。您需要Appointment
中的第二对 FK 和导航属性(或映射一个没有反向属性的关系):
modelBuilder.Entity<Calendar>()
.HasMany(c => c.FreeSlots)
.WithRequired(c => c.Calendar1)
.HasForeignKey(c => c.Calendar1ID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Calendar>()
.HasMany(c => c.AppointmentsList)
.WithRequired(c => c.Calendar2)
.HasForeignKey(c => c.Calendar2ID)
.WillCascadeOnDelete(true);
(对于至少一个关系,您必须禁用级联删除。否则您最终会遇到多重级联删除异常。)
但是,我感觉您实际上应该只有一个关系和集合Calendar.Appointments
和Appointment
中的一种状态,例如bool IsFree
属性。然后,您始终可以使用calendar.Appointments.Where(a => a.IsFree)
提取日历条目的空闲槽。
【讨论】:
谢谢@Slauma!这解决了我的问题。你对 bool 属性是正确的,实际上我使用了两个从 Appointment 继承的不同实体。无论如何,我不明白我的映射有什么问题,但现在我明白了:) 我正在尝试做类似的事情。我有一个包含电子邮件和电话的联系人。我想将电子邮件和电话组合在一个名为 CONTACTINFO 的实体中,该实体可以具有 ContactInfoType 属性(枚举)来区分它们。如果有办法在模型构建器中使用默认 WHERE 子句/条件的导航属性?以上是关于同一实体类型代码的多个一对多关系优先的主要内容,如果未能解决你的问题,请参考以下文章