2012-04-27 150 views
0

我有两个实体对象:多对多的关系EF

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。

我该如何去确定是否生成了正确的关系?

+0

[多对一的可能重复许多关系在代码优先EF4](http://stackoverflow.com/questions/3148844/many-to-many-relationship-in-code-first-ef4) – StriplingWarrior 2012-04-27 19:24:23

回答

0

我想你想让两行的朋友引用两个联系人,对不对?如果是的话,你需要创建两个朋友的实例。实体框架代码首先在默认情况下通过您的财产的名称来识别关键关系 。因此,在您的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; } 
} 
+0

dknaack,如果我想要一个朋友行是与两个联系人关联?如果我在设计数据库,那么ContactId1将指向联系人表,并且ContactId2也将指向联系人表。 – 2012-04-27 19:49:48

+0

这对我的解决方案是可行的。 – dknaack 2012-04-27 19:54:17

+0

我的解决方案说...它不可能有两个相同的朋友和相同的联系人的行是可能的。你可以让几个朋友拥有相同的联系人和几个联系人以拥有相同的朋友。这很多很多 – dknaack 2012-04-27 19:56:44

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; } 
} 

和属性在Contact添加到Friends集合:

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

(你也可以用流利的API,而不是注解)

结果是两个一对多关系(您不能将此模型映射为多对多)。第一个是Contact.FriendsFriend.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(); 

EIT

上述映射不起作用,因为Friend有两个必需的关系Contact。默认情况下,对于所需的一对多关系,EF将启用级联删除,但不允许两个关系同时使用。我们需要重写用流利的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 
} 
+0

感谢Slauma--但运行我的应用程序时出现错误 - 未处理的异常:系统.InvalidOperationException:数据库创建成功,但不创建数据库对象。有关更多详情,请参阅内部例外---> System.Data.SqlServerCe.SqlCeException:参考相关将导致不允许的循环引用。 [约束名=联系朋友] ..想法? – 2012-04-30 12:41:51

+0

@ek_ny:看我上面的编辑。我不确定它是否能解决问题,请告诉我是否可以解决问题。 – Slauma 2012-04-30 13:01:15