我有两个实体对象:
public class Contact
{
public int ContactID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public ICollection<Friend> Friends { get; set; }
}
和朋友:
public class Friend
{
[Key, Column(Order = 1)]
public int ContactId1 { get; set; }
[Key, Column(Order = 1)]
public int ContactId2 { get; set; }
public DateTime DateCreated { get; set; }
}
其中 ContactId1 映射回 ContactID,ContactId2 映射回另一个 ContactId。
我如何确保以适当的关系生成?
你需要扩展你的Friend
类:
public class Friend
{
[Key, Column(Order = 0), ForeignKey("Contact1")]
public int ContactId1 { get; set; }
public Contact Contact1 { get; set; }
[Key, Column(Order = 1), ForeignKey("Contact2")]
public int ContactId2 { get; set; }
public Contact Contact2 { get; set; }
public DateTime DateCreated { get; set; }
}
并在 Contact
中向Friends
集合添加一个属性:
[InverseProperty("Contact1")]
public ICollection<Friend> Friends { get; set; }
(您也可以使用 Fluent API 代替注释。
结果是两个一对多关系(不能将此模型映射为多对多)。第一个介于 Contact.Friends
和 Friend.Contact1
之间,第二个终结点Friend.Contact2
。Friend
中的端点不会在模型中公开。
然后,您可以查询例如今天之前创建的给定联系人的所有朋友联系人:
DateTime today = DateTime.Now.Date;
IEnumerable<Contact> friendContacts = context.Contacts
.Where(c => c.ContactId == givenId)
.Select(c => c.Friends
.Where(f => f.DateCreated < today)
.Select(f => f.Contact2))
.SingleOrDefault();
艾特
上面的映射不起作用,因为Friend
有两个必需的关系来Contact
。默认情况下,对于所需的一对多关系,EF 将启用级联删除,不允许同时使用两个关系。我们需要使用 Fluent API 重写映射以禁用级联删除,因为这在数据注释中是不可能的:
public class Contact
{
public int ContactID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public ICollection<Friend> Friends { get; set; }
}
public class Friend
{
public int ContactID1 { get; set; }
public Contact Contact1 { get; set; }
public int ContactID2 { get; set; }
public Contact Contact2 { get; set; }
public DateTime DateCreated { get; set; }
}
然后在派生上下文中重写OnModelCreating
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Friend>()
.HasKey(f => new { f.ContactID1, f.ContactID2 });
modelBuilder.Entity<Friend>()
.HasRequired(f => f.Contact1)
.WithMany(c => c.Friends)
.HasForeignKey(f => f.ContactID1);
modelBuilder.Entity<Friend>()
.HasRequired(f => f.Contact2)
.WithMany()
.HasForeignKey(f => f.ContactID2)
.WillCascadeOnDelete(false); // <- Important
}
我想你想要两排朋友在联系时推荐两个,对吧?如果是,您需要两个创建到朋友的实例。默认情况下,实体框架代码优先识别按您的财产名称划分的关键关系。所以在你的朋友类中,属性应该名称联系人 ID,因为实体是名称联系人。
public class Contact
{
public int ContactID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public ICollection<Friend> Friends { get; set; }
}
public class Friend
{
public int ContactId { get; set; }
public DateTime DateCreated { get; set; }
}
编辑
如果你想让一个朋友有很多联系人,你需要一个关系表。
public class Contact
{
public int ContactID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public ICollection<Friend> Friends { get; set; }
}
public class Friend
{
public int FriendId { get; set; }
public DateTime DateCreated { get; set; }
}
public class FriendContactRel
{
[Key, Column(Order = 0)]
public int ContactID { get; set; }
[Key, Column(Order = 1)]
public int FriendId { get; set; }
}