ฉันได้ค้นหา StackOverflow สำหรับการแก้ปัญหาที่เหมาะสมในการสร้างหลายต่อหลายความสัมพันธ์โดยใช้ EF หลักรหัสแรกและคล่องแคล่ว API
สถานการณ์ง่ายๆคือ:
public class Person
{
public Person() {
Clubs = new HashSet<Club>();
}
public int PersonId { get; set; }
public virtual ICollection<Club> Clubs { get; set; }
}
public class Club
{
public Club() {
Persons = new HashSet<Person>();
}
public int ClubId { get; set; }
public virtual ICollection<Person> Persons { get; set; }
}
โปรดแก้ไขฉันหากฉันผิด แต่ฉันไม่พบคำถามที่มีคำอธิบายอย่างละเอียดเกี่ยวกับวิธีดำเนินการนี้โดยใช้เครื่องมือที่อธิบายไว้ ใครสามารถอธิบายได้ว่าทำอย่างไร
EF Core 5.0 RC1 +
ในส่วนของ EF Core 5.0 RC1 สามารถทำได้โดยไม่ต้องมีตารางการรวมที่ชัดเจน EF Core สามารถกำหนดค่าการแมปสำหรับความสัมพันธ์แบบกลุ่มต่อกลุ่มที่แสดงในคำถามของคุณโดยไม่ต้องให้คุณสร้างPersonClubประเภท
ดูว่ามีอะไรใหม่ใน EF Core 5.0, RC1, Many-to-manyในเอกสารอย่างเป็นทางการสำหรับข้อมูลเพิ่มเติม
เวอร์ชันก่อนหน้า
สิ่งนี้ยังไม่สามารถทำได้ใน EF Core โดยไม่ต้องใช้คลาสที่ชัดเจนสำหรับการเข้าร่วม ดูที่นี่สำหรับตัวอย่างของวิธีการทำว่า
มีปัญหาที่เปิดอยู่ใน Github ที่ขอความสามารถในการทำสิ่งนี้โดยไม่จำเป็นต้องมีคลาสที่ชัดเจน แต่ยังไม่เสร็จสมบูรณ์
เมื่อใช้สถานการณ์ของคุณตัวอย่างที่ฉันเชื่อมโยงจะแนะนำคลาสเอนทิตีต่อไปนี้:
public class Person
{
public int PersonId { get; set; }
public virtual ICollection<PersonClub> PersonClubs { get; set; }
}
public class Club
{
public int ClubId { get; set; }
public virtual ICollection<PersonClub> PersonClubs { get; set; }
}
public class PersonClub
{
public int PersonId { get; set; }
public Person Person { get; set; }
public int ClubId { get; set; }
public Club Club { get; set; }
}
OnModelCreatingจากนั้นจะใช้สิ่งต่อไปนี้สำหรับการตั้งค่า:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PersonClub>()
.HasKey(pc => new { pc.PersonId, pc.ClubId });
modelBuilder.Entity<PersonClub>()
.HasOne(pc => pc.Person)
.WithMany(p => p.PersonClubs)
.HasForeignKey(pc => pc.PersonId);
modelBuilder.Entity<PersonClub>()
.HasOne(pc => pc.Club)
.WithMany(c => c.PersonClubs)
.HasForeignKey(pc => pc.ClubId);
}
อย่าลืมไปที่ปัญหาเปิดที่ฉันเชื่อมโยงและแสดงความไม่พอใจของคุณหากคุณรู้สึกว่าต้องการ
แก้ไข: ปัญหาที่เปิดอยู่แนะนำให้ใช้วิธีง่ายๆSelectในการนำทางผ่านลำดับชั้นที่ค่อนข้างยุ่งยากนี้ เพื่อที่จะได้รับจากPersonIdคอลเลกชันของClubs SelectManyคุณสามารถใช้ เช่น:
var clubs = dbContext.People
.Where(p => p.PersonId == id)
.SelectMany(p => p.PersonClubs);
.Select(pc => pc.Club);
ฉันไม่สามารถรับรองได้ว่านี่เป็น "แนวทางปฏิบัติที่ดีที่สุด" จริง ๆ หรือไม่ แต่มันควรจะเป็นเคล็ดลับอย่างแน่นอนและฉันคิดว่ามันยุติธรรมที่จะบอกว่ามันไม่น่าเกลียดเกินไป
"การตั้งค่า" ที่ถูกต้องสำหรับสิ่งนี้คือ:
public class Person
{
public int PersonId { get; set; }
public virtual ICollection<PersonClub> PersonClubs { get; set; }
}
public class Club
{
public int ClubId { get; set; }
public virtual ICollection<PersonClub> PersonClubs { get; set; }
}
public class PersonClub
{
public int PersonId { get; set; }
public Person Person { get; set; }
public int ClubId { get; set; }
public Club Club { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PersonClub>()
.HasKey(pc => new { pc.PersonId, pc.ClubId });
}
ดังนั้นบล็อกนี้สำหรับการกำหนดค่า "glue-table" จึงไม่จำเป็นในตัวอย่าง @Kirk:
modelBuilder.Entity<PersonClub>()
.HasOne(pc => pc.Person)
.WithMany(p => p.PersonClubs)
.HasForeignKey(pc => pc.PersonId);
modelBuilder.Entity<PersonClub>()
.HasOne(pc => pc.Club)
.WithMany(c => c.PersonClubs)
.HasForeignKey(pc => pc.ClubId);
ดังนั้นทุกคนPersonมีศูนย์หรือมากกว่าClubsและทุกมีศูนย์หรือมากกว่าClub Personsตามที่คุณระบุไว้อย่างถูกต้องนี่คือความสัมพันธ์แบบกลุ่มต่อกลุ่มที่เหมาะสม
คุณคงทราบดีว่าฐานข้อมูลเชิงสัมพันธ์ต้องการตารางพิเศษเพื่อใช้ความสัมพันธ์แบบกลุ่มต่อกลุ่มนี้ สิ่งที่ดีเกี่ยวกับกรอบงานเอนทิตีคือมันรับรู้ความสัมพันธ์นี้และสร้างตารางพิเศษนี้ให้คุณ
เมื่อมองแวบแรกดูเหมือนว่าจะมีปัญหาว่าโต๊ะพิเศษนี้ไม่ได้dbSetอยู่ในDbContext: "จะเข้าร่วมกับโต๊ะเสริมนี้ได้อย่างไรหากฉันไม่มีDbSet"
โชคดีที่คุณไม่จำเป็นต้องพูดถึงตารางพิเศษนี้ในคำถามของคุณ
หากคุณต้องการคำถามเช่น "Give me all 'Clubs' that ... from every 'Person' who ... " don't think in join. ใช้ ICollections แทน!
รับบุคคล "John Doe" ทั้งหมดที่มี Country Club ทั้งหมดที่เข้าร่วม:
var result = myDbContext.Persons
.Where(person => person.Name == "John Doe")
.Select(person => new
{
PersonId = person.Id,
PersonName = person.Name,
AttendedCountryClubs = person.Clubs
.Where(club => club.Type = ClubType.CountryClub),
};
เอนทิตีเฟรมเวิร์กจะรับรู้ว่าจำเป็นต้องมีการเข้าร่วมกับตารางแบบกลุ่มต่อกลุ่มเพิ่มเติมและจะดำเนินการเข้าร่วมนี้โดยที่คุณไม่ต้องพูดถึงตารางพิเศษนี้
ในทางกลับกัน: รับสโมสรในประเทศทั้งหมดที่มีบุคคล "John Doe" ของพวกเขา:
var result = myDbContext.Clubs
.Where(club => club.Type = ClubType.CountryClub)
.Select(club => new
{
ClubId = club.Id,
ClubName = club.Name,
AnonymousMembers = club.Persons
.Where(person => person.Name == "John Doe"),
}
ฉันเคยพบว่าเมื่อฉันเริ่มคิดถึงคอลเล็กชันผลลัพธ์ที่ฉันต้องการแทนที่จะเป็นการรวมที่ฉันต้องการเพื่อรับคอลเล็กชันเหล่านี้ฉันพบว่าฉันแทบจะไม่ได้ใช้การรวมเลย นี่เป็นกรณีของความสัมพันธ์แบบหนึ่งต่อกลุ่มและความสัมพันธ์แบบกลุ่มต่อกลุ่ม กรอบเอนทิตีจะใช้การรวมที่เหมาะสมภายใน
Jana Duggar เปิดใจเกี่ยวกับการค้นหาความรักของเธอ นี่คือทุกสิ่งที่เธอพูดเกี่ยวกับหัวข้อและกรอบเวลา 5 ปีสำหรับการแต่งงาน
เมื่อเร็ว ๆ นี้ แซม ฮิวแฮน นักแสดงจากเรื่อง 'Outlander' ได้เปิดเผยสิ่งที่เขาจะทำจากกองถ่ายเพื่อระลึกถึงเจมี เฟรเซอร์ บทบาทที่ทำให้เขากลายเป็นดารา
'She Loves You' เขียนขึ้นในหนึ่งชั่วโมง บันทึกเสียงในหนึ่งวัน และเป็นเพลงของ The Beatles ที่มีการแสดงที่ดีที่สุดเพลงหนึ่งในอาชีพของพวกเขา
Dolly Parton และคุณย่า Bessie มีความสัมพันธ์พิเศษ คุณยายพาร์ตันป่วยหนัก แต่นั่นไม่ได้ทำให้ดอลลี่หยุดแกล้งเธอ
คุณอาจคิดว่าไม้โอ๊คหรือฮิคคอรีเป็นไม้ที่แข็ง แต่เมื่อต้องพูดถึงไม้ที่แข็งที่สุดในโลกแล้ว พวกมันกลับไม่ใกล้เคียงเลย
มหาสมุทรเต็มไปด้วยความงาม แต่ก็ซ่อนสิ่งมีชีวิตใต้ท้องทะเลที่น่ากลัวที่สุดบางชนิดไว้เช่นกัน สัตว์เหล่านี้หลายชนิดซ่อนตัวอยู่ใต้ผิวน้ำอันมืดมิด ในโลกใต้ทะเลลึกอันแสนกดดันและมืดมิด
หากคุณกำลังต่อสู้กับศัตรูหรือกำลังเตรียมตัวสำหรับโหมด PvP การรู้ถึงการเสริมพลังดาบที่ดีที่สุดใน Minecraft จะช่วยให้คุณได้เปรียบอย่างมาก การเสริมพลังดาบจะช่วยให้คุณสร้างความเสียหายได้มากขึ้น เพิ่มจำนวนม็อบที่ดรอป และเพิ่มความทนทานของดาบ
เมื่อผู้คนพูดถึงประเทศสังคมนิยม พวกเขามักจะนึกถึงการควบคุมโดยรัฐบาลอย่างเต็มรูปแบบโดยไม่มีกรรมสิทธิ์ส่วนบุคคล แต่ในทางปฏิบัติ เศรษฐกิจแบบสังคมนิยมมีความหลากหลายอย่างมาก
“เด็ก” โผล่รับเชิญดาราดังพร้อมข่าวร้าย
RAV4 นี้อ้างว่าอยู่ในสภาพที่ดีเยี่ยมและมีไว้สำหรับการเล่นเก้าอี้ดนตรี
ภาพจากโดรนจับภาพนักดับเพลิงที่กำลังพยายามดับไฟ
Eyes of Wakanda เชื่อมโยงโดยตรงกับ MCU พร้อมอัปเดตเกี่ยวกับ X-Men '97, What If..., Daredevil และอีกมากมาย
Ava Gardner แต่งงานกับ Mickey Rooney และ Frank Sintra และเธอยังคบหาดูใจกับดาราฮอลลีวูดอีกหลายคน ต่อไปนี้คือประวัติการออกเดทของ Ava Gardner
จอห์น คลีส แต่งงานกับเจนนิเฟอร์ เวด ภรรยาของเขาในปี 2012 นี่คือทุกสิ่งที่คุณต้องรู้เกี่ยวกับเจนนิเฟอร์ เวด ภรรยาของจอห์น คลีส
Michael C. Hall แต่งงานกับ Morgan Macgregor ภรรยาของเขาตั้งแต่ปี 2016 นี่คือทุกสิ่งที่คุณต้องการทราบเกี่ยวกับภรรยาของ Michael C. Hall
Mena Suvari แต่งงานกับ Michael Hope สามีของเธอมาตั้งแต่ปี 2018 นี่คือทุกสิ่งที่ควรรู้เกี่ยวกับสามีของ Mena Suvari
มันทำให้ฉันประหลาดใจ ทันใดนั้นมันก็เกิดขึ้นบ่อยๆ มันอยู่กลางทางอีกครั้ง <ไม่ ไม่ใช่คนในมหาสมุทรแปซิฟิก คุณเป็นสีน้ำตาลแดง คนที่งานคาร์นิวัล> ทุกพาดหัวข่าวดัง…..
ในปี 2022 ด้วยการเปิดตัว GPT-3 ทักษะการเขียนดูเหมือนจะมีความสำคัญน้อยลง ด้วย AI คนที่เขียนไม่ดีก็สามารถสร้างพนักงานที่มีคุณภาพได้เช่นกัน
ในโลกที่เปลี่ยนแปลงอย่างรวดเร็วและการแข่งขันในปัจจุบัน อาชีพของคนๆ หนึ่งมีบทบาทสำคัญในการเติบโตส่วนบุคคล ความมั่นคงทางการเงิน และความพึงพอใจในชีวิตโดยรวม อย่างไรก็ตาม ผู้คนจำนวนมากพบว่าตัวเองติดอยู่ในวงจรของความเมื่อยล้าและความไม่พอใจอย่างไม่หยุดยั้ง ค่อยๆ สูญเสียชีวิตการทำงานไป
เมื่อสัปดาห์ที่แล้วฉันสังเกตเห็นข่าวประชาสัมพันธ์ที่เผยแพร่ผ่าน PressGazette (เว็บไซต์ข่าวของสื่ออังกฤษ) บทความประกาศว่า Acast ซึ่งเป็นบริษัทโฮสติ้งและโฆษณาพอดคาสต์ของ Scandi จะเป็นผู้นำกลุ่มผู้เผยแพร่ "อาจมีอิทธิพลมากที่สุด" ในพอดคาสต์