首先创build代码,多到很多,并在关联表中添加额外的字段

我有这种情况:

public class Member { public int MemberID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public virtual ICollection<Comment> Comments { get; set; } } public class Comment { public int CommentID { get; set; } public string Message { get; set; } public virtual ICollection<Member> Members { get; set; } } public class MemberComment { public int MemberID { get; set; } public int CommentID { get; set; } public int Something { get; set; } public string SomethingElse { get; set; } } 

我如何configurationstream畅API的关联? 还是有更好的方法来创build关联表?

使用自定义连接表创build多对多关系是不可能的。 在多对多关系中,EF在内部pipe理连接表并隐藏。 这是一个没有实体类的表格。 要处理这样一个连接表和其他属性,你将不得不创build两个一对多的关系。 它可能是这样的:

 public class Member { public int MemberID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public virtual ICollection<MemberComment> MemberComments { get; set; } } public class Comment { public int CommentID { get; set; } public string Message { get; set; } public virtual ICollection<MemberComment> MemberComments { get; set; } } public class MemberComment { [Key, Column(Order = 0)] public int MemberID { get; set; } [Key, Column(Order = 1)] public int CommentID { get; set; } public virtual Member Member { get; set; } public virtual Comment Comment { get; set; } public int Something { get; set; } public string SomethingElse { get; set; } } 

如果你现在想findLastName =“Smith”的成员的所有评论,例如你可以写一个这样的查询:

 var commentsOfMembers = context.Members .Where(m => m.LastName == "Smith") .SelectMany(m => m.MemberComments.Select(mc => mc.Comment)) .ToList(); 

…要么…

 var commentsOfMembers = context.MemberComments .Where(mc => mc.Member.LastName == "Smith") .Select(mc => mc.Comment) .ToList(); 

或者创build一个名为“Smith”(我们假设有多个)的成员名单以及他们的评论,你可以使用一个投影:

 var membersWithComments = context.Members .Where(m => m.LastName == "Smith") .Select(m => new { Member = m, Comments = m.MemberComments.Select(mc => mc.Comment) }) .ToList(); 

如果您想查找MemberId = 1的成员的所有评论:

 var commentsOfMember = context.MemberComments .Where(mc => mc.MemberId == 1) .Select(mc => mc.Comment) .ToList(); 

现在,您也可以通过连接表中的属性进行过滤(这在多对多关系中是不可能的),例如:过滤所有具有99属性的成员1的所有注释Something

 var filteredCommentsOfMember = context.MemberComments .Where(mc => mc.MemberId == 1 && mc.Something == 99) .Select(mc => mc.Comment) .ToList(); 

由于懒加载事情可能会变得更容易。 如果你有一个加载Member你应该能够得到没有明确查询的评论:

 var commentsOfMember = member.MemberComments.Select(mc => mc.Comment); 

我猜延迟加载会在幕后自动获取注释。

编辑

只是为了好玩几个例子,更多的是如何添加实体和关系,以及如何在这个模型中删除它们:

1)创build该会员的一个会员和两个评论:

 var member1 = new Member { FirstName = "Pete" }; var comment1 = new Comment { Message = "Good morning!" }; var comment2 = new Comment { Message = "Good evening!" }; var memberComment1 = new MemberComment { Member = member1, Comment = comment1, Something = 101 }; var memberComment2 = new MemberComment { Member = member1, Comment = comment2, Something = 102 }; context.MemberComments.Add(memberComment1); // will also add member1 and comment1 context.MemberComments.Add(memberComment2); // will also add comment2 context.SaveChanges(); 

2)添加member1的第三条评论:

 var member1 = context.Members.Where(m => m.FirstName == "Pete") .SingleOrDefault(); if (member1 != null) { var comment3 = new Comment { Message = "Good night!" }; var memberComment3 = new MemberComment { Member = member1, Comment = comment3, Something = 103 }; context.MemberComments.Add(memberComment3); // will also add comment3 context.SaveChanges(); } 

3)创build新成员并将其与现有的评论2相关联:

 var comment2 = context.Comments.Where(c => c.Message == "Good evening!") .SingleOrDefault(); if (comment2 != null) { var member2 = new Member { FirstName = "Paul" }; var memberComment4 = new MemberComment { Member = member2, Comment = comment2, Something = 201 }; context.MemberComments.Add(memberComment4); context.SaveChanges(); } 

4)创build现有member2和comment3之间的关系:

 var member2 = context.Members.Where(m => m.FirstName == "Paul") .SingleOrDefault(); var comment3 = context.Comments.Where(c => c.Message == "Good night!") .SingleOrDefault(); if (member2 != null && comment3 != null) { var memberComment5 = new MemberComment { Member = member2, Comment = comment3, Something = 202 }; context.MemberComments.Add(memberComment5); context.SaveChanges(); } 

5)再次删除这个关系:

 var memberComment5 = context.MemberComments .Where(mc => mc.Member.FirstName == "Paul" && mc.Comment.Message == "Good night!") .SingleOrDefault(); if (memberComment5 != null) { context.MemberComments.Remove(memberComment5); context.SaveChanges(); } 

6)删除member1及其所有与注释的关系:

 var member1 = context.Members.Where(m => m.FirstName == "Pete") .SingleOrDefault(); if (member1 != null) { context.Members.Remove(member1); context.SaveChanges(); } 

这也会删除MemberComments的关系,因为MemberMemberComments之间以及CommentMemberComments之间的一对多关系是按照惯例使用级联删除来设置的。 这是因为MemberComment中的MemberIdCommentId被检测为MemberComment导航属性的外键属性,并且由于FK属性的types不可为空,所以最终导致级联 – 删除 – 设置的关系是必需的。 我觉得在这个模型中是有道理的。

Slauma非常好的回答。

我只是发表代码来做到这一点使用stream利的API映射。

 public class User { public int UserID { get; set; } public string Username { get; set; } public string Password { get; set; } public ICollection<UserEmail> UserEmails { get; set; } } public class Email { public int EmailID { get; set; } public string Address { get; set; } public ICollection<UserEmail> UserEmails { get; set; } } public class UserEmail { public int UserID { get; set; } public int EmailID { get; set; } public bool IsPrimary { get; set; } } 

在你的DbContext派生类,你可以这样做:

 public class MyContext : DbContext { protected override void OnModelCreating(DbModelBuilder builder) { // Primary keys builder.Entity<User>().HasKey(q => q.UserID); builder.Entity<Email>().HasKey(q => q.EmailID); builder.Entity<UserEmail>().HasKey(q => new { q.UserID, q.EmailID }); // Relationships builder.Entity<UserEmail>() .HasRequired(t => t.Email) .WithMany(t => t.UserEmails) .HasForeignKey(t => t.EmailID) builder.Entity<UserEmail>() .HasRequired(t => t.User) .WithMany(t => t.UserEmails) .HasForeignKey(t => t.UserID) } } 

它与被接受的答案具有相同的效果,采用不同的方法,这不是好的也不坏的。

编辑: 我已经把从BOOL CreatedDate DateTime。

编辑2:由于缺乏时间,我已经从应用程序中放置了一个示例,我正在努力确保它能正常工作。

@Esteban,你提供的代码是正确的,谢谢,但不完整,我已经testing过。 “UserEmail”类中缺less属性:

  public UserTest UserTest { get; set; } public EmailTest EmailTest { get; set; } 

我发布了我testing过的代码,如果有人感兴趣。 问候

 using System.Data.Entity; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Web; #region example2 public class UserTest { public int UserTestID { get; set; } public string UserTestname { get; set; } public string Password { get; set; } public ICollection<UserTestEmailTest> UserTestEmailTests { get; set; } public static void DoSomeTest(ApplicationDbContext context) { for (int i = 0; i < 5; i++) { var user = context.UserTest.Add(new UserTest() { UserTestname = "Test" + i }); var address = context.EmailTest.Add(new EmailTest() { Address = "address@" + i }); } context.SaveChanges(); foreach (var user in context.UserTest.Include(t => t.UserTestEmailTests)) { foreach (var address in context.EmailTest) { user.UserTestEmailTests.Add(new UserTestEmailTest() { UserTest = user, EmailTest = address, n1 = user.UserTestID, n2 = address.EmailTestID }); } } context.SaveChanges(); } } public class EmailTest { public int EmailTestID { get; set; } public string Address { get; set; } public ICollection<UserTestEmailTest> UserTestEmailTests { get; set; } } public class UserTestEmailTest { public int UserTestID { get; set; } public UserTest UserTest { get; set; } public int EmailTestID { get; set; } public EmailTest EmailTest { get; set; } public int n1 { get; set; } public int n2 { get; set; } //Call this code from ApplicationDbContext.ConfigureMapping //and add this lines as well: //public System.Data.Entity.DbSet<yournamespace.UserTest> UserTest { get; set; } //public System.Data.Entity.DbSet<yournamespace.EmailTest> EmailTest { get; set; } internal static void RelateFluent(System.Data.Entity.DbModelBuilder builder) { // Primary keys builder.Entity<UserTest>().HasKey(q => q.UserTestID); builder.Entity<EmailTest>().HasKey(q => q.EmailTestID); builder.Entity<UserTestEmailTest>().HasKey(q => new { q.UserTestID, q.EmailTestID }); // Relationships builder.Entity<UserTestEmailTest>() .HasRequired(t => t.EmailTest) .WithMany(t => t.UserTestEmailTests) .HasForeignKey(t => t.EmailTestID); builder.Entity<UserTestEmailTest>() .HasRequired(t => t.UserTest) .WithMany(t => t.UserTestEmailTests) .HasForeignKey(t => t.UserTestID); } } #endregion 

TLDR; (与EF6 / VS2012U5中的EF编辑器错误半相关),如果从DB生成模型,并且看不到属性的m:m表:删除两个相关的表 – >保存.edmx – >从数据库生成/添加 – >保存。

对于那些来这里想知道如何获得一个多对多的关系与属性列显示在EF .EDMX文件(因为它目前不会显示和被视为一组导航属性),你生成这些类从你的数据库表(或数据库 – 首先在MS术语,我相信。)

删除您的.edmx中的两个表(以获取OP示例,成员和评论),并通过“从数据库生成模型”再次添加它们。 (即不要试图让Visual Studio更新它们 – 删除,保存,添加,保存)

然后它将创build一个与这里build议的内容一致的第三个表格。

这在最初添加纯多对多关系并且稍后在数据库中devise属性的情况下是相关的。

这个线程/谷歌search没有立即清楚。 所以只是把它放在那里,因为这是谷歌链接#1寻找问题,但首先来自数据库方面。