เป็นไปไม่ได้ที่จะสร้างความสัมพันธ์แบบกลุ่มต่อกลุ่มด้วยตารางการเข้าร่วมที่กำหนดเอง ในความสัมพันธ์แบบกลุ่มต่อกลุ่ม EF จัดการตารางการเข้าร่วมภายในและซ่อนเร้น เป็นตารางที่ไม่มีคลาส Entity ในโมเดลของคุณ หากต้องการทำงานกับตารางการเข้าร่วมที่มีคุณสมบัติเพิ่มเติมคุณจะต้องสร้างความสัมพันธ์แบบหนึ่งต่อหลายสองอย่าง มันอาจมีลักษณะเช่นนี้:
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; }
}
หากตอนนี้คุณต้องการค้นหาความคิดเห็นทั้งหมดของสมาชิกที่มีLastName
= "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();
หรือเพื่อสร้างรายชื่อสมาชิกที่มีชื่อ "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();
ตอนนี้คุณสามารถกรองตามคุณสมบัติในตารางการเข้าร่วมของคุณ (ซึ่งอาจเป็นไปไม่ได้ในความสัมพันธ์แบบกลุ่มต่อกลุ่ม) ตัวอย่างเช่น: กรองความคิดเห็นทั้งหมดของสมาชิก 1 ที่มีคุณสมบัติ 99 รายการ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) สร้างหนึ่งสมาชิกและสองความคิดเห็นของสมาชิกนี้:
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) สร้างสมาชิกใหม่และเชื่อมโยงกับความคิดเห็นที่มีอยู่ 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) สร้างความสัมพันธ์ระหว่าง member2 ที่มีอยู่และข้อคิดเห็น 3:
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
เกินไปเพราะความสัมพันธ์แบบหนึ่งต่อหลายระหว่างMember
และMemberComments
ระหว่างComment
และMemberComments
มีการติดตั้งกับ cascading ลบโดยการประชุม และเป็นกรณีที่เพราะMemberId
และCommentId
ในMemberComment
จะถูกตรวจพบว่าเป็นคุณสมบัติที่สำคัญต่างประเทศสำหรับMember
และComment
คุณสมบัตินำทางและตั้งแต่คุณสมบัติ FK เป็นประเภทที่ไม่ใช่ nullable int
ความสัมพันธ์เป็นสิ่งจำเป็นที่สุดซึ่งเป็นสาเหตุที่ทำให้ซ้อน-ลบการติดตั้ง ฉันคิดว่ามันสมเหตุสมผลสำหรับรุ่นนี้