Tidak mungkin untuk membuat hubungan banyak-ke-banyak dengan tabel bergabung khusus. Dalam hubungan banyak-ke-banyak, EF mengelola tabel bergabung secara internal dan tersembunyi. Ini adalah tabel tanpa kelas Entity di model Anda. Untuk bekerja dengan tabel gabungan seperti itu dengan properti tambahan, Anda harus membuat sebenarnya dua hubungan satu-ke-banyak. Itu bisa terlihat seperti ini:
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; }
}
Jika sekarang Anda ingin menemukan semua komentar anggota dengan LastName
= "Smith" misalnya, Anda dapat menulis kueri seperti ini:
var commentsOfMembers = context.Members
.Where(m => m.LastName == "Smith")
.SelectMany(m => m.MemberComments.Select(mc => mc.Comment))
.ToList();
... atau ...
var commentsOfMembers = context.MemberComments
.Where(mc => mc.Member.LastName == "Smith")
.Select(mc => mc.Comment)
.ToList();
Atau untuk membuat daftar anggota dengan nama "Smith" (kami menganggap ada lebih dari satu) bersama dengan komentar mereka, Anda dapat menggunakan proyeksi:
var membersWithComments = context.Members
.Where(m => m.LastName == "Smith")
.Select(m => new
{
Member = m,
Comments = m.MemberComments.Select(mc => mc.Comment)
})
.ToList();
Jika Anda ingin menemukan semua komentar anggota dengan MemberId
= 1:
var commentsOfMember = context.MemberComments
.Where(mc => mc.MemberId == 1)
.Select(mc => mc.Comment)
.ToList();
Sekarang Anda juga dapat memfilter menurut properti di tabel bergabung Anda (yang tidak mungkin terjadi dalam hubungan banyak ke banyak), misalnya: Saring semua komentar anggota 1 yang memiliki 99 properti Something
:
var filteredCommentsOfMember = context.MemberComments
.Where(mc => mc.MemberId == 1 && mc.Something == 99)
.Select(mc => mc.Comment)
.ToList();
Karena memuat malas mungkin menjadi lebih mudah. Jika Anda telah memuat Member
Anda harus bisa mendapatkan komentar tanpa permintaan eksplisit:
var commentsOfMember = member.MemberComments.Select(mc => mc.Comment);
Saya kira pemuatan malas akan mengambil komentar secara otomatis di belakang layar.
Edit
Hanya untuk bersenang-senang beberapa contoh lebih banyak cara menambahkan entitas dan hubungan dan cara menghapusnya dalam model ini:
1) Buat satu anggota dan dua komentar dari anggota ini:
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) Tambahkan komentar ketiga 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) Buat anggota baru dan hubungkan dengan komentar2 yang ada:
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) Buat hubungan antara member2 yang ada dan 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) Hapus hubungan ini lagi:
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) Hapus member1 dan semua hubungannya dengan komentar:
var member1 = context.Members.Where(m => m.FirstName == "Pete")
.SingleOrDefault();
if (member1 != null)
{
context.Members.Remove(member1);
context.SaveChanges();
}
Ini juga menghapus hubungan MemberComments
karena hubungan satu-ke-banyak antara Member
dan MemberComments
dan di antara Comment
dan MemberComments
diatur dengan penghapusan cascading oleh konvensi. Dan ini terjadi karena MemberId
dan CommentId
dalam MemberComment
terdeteksi sebagai properti kunci asing untuk Member
dan Comment
navigasi properti dan karena properti FK bertipe non-nullable int
hubungan diperlukan yang akhirnya menyebabkan cascading-delete-setup. Masuk akal dalam model ini, saya pikir.