0

我有两个实体对象:

   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。

如何确保生成正确的关系?

4

2 回答 2

2

您需要扩展您的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; }
}

Friends并在集合中添加一个属性Contact

[InverseProperty("Contact1")]
public ICollection<Friend> Friends { get; set; }

(您也可以使用 Fluent API 代替注解。)

结果是两个一对多的关系(您不能将此模型映射为多对多)。第一个在Contact.Friends和之间Friend.Contact1,第二个Friend.Contact2作为一个端点。端点 inFriend未在模型中公开。

然后,您可以查询例如在今天之前创建的给定联系人的所有朋友联系人:

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();

伊特

上面的映射不起作用,因为FriendContact. 默认情况下,对于所需的一对多关系,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
}
于 2012-04-27T20:12:10.383 回答
0

我想你想要两排朋友在联系时推荐两个,对吧?如果是,您需要两个创建朋友的实例。默认情况下,Entity Framework Code First 确实通过您的属性名称识别键关系。因此,在您的 Friend 类中,该属性应命名为 ContactId,因为实体名称为 Contact。

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; }
}
于 2012-04-27T19:26:46.880 回答