Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Megjegyzés:
Ez a lap a fluent API használatával a Code First modellben lévő kapcsolatok beállításáról nyújt tájékoztatást. Az EF-kapcsolatokról és az adatok kapcsolatok használatával való eléréséről és módosításáról a Kapcsolatok > navigációs tulajdonságok című témakörben olvashat.
A Code First használatakor a modellt a tartományi CLR-osztályok definiálásával határozhatja meg. Az Entity Framework alapértelmezés szerint a Code First konvenciók használatával rendeli le az osztályokat az adatbázissémához. A Code First elnevezési konvenciók használata esetén a legtöbb esetben a Code First használatával állíthatja be a táblák közötti kapcsolatokat az osztályokban megadott idegen kulcsok és navigációs tulajdonságok alapján. Ha az osztályok meghatározásakor nem követi az egyezményeket, vagy ha módosítani szeretné a konvenciók működését, a fluent API-val vagy adatjegyzetekkel konfigurálhatja az osztályokat, hogy a Code First leképezhesse a táblák közötti kapcsolatokat.
Introduction
A fluent API-val való kapcsolat konfigurálásakor először az EntityTypeConfiguration példányt kell használnia, majd a HasRequired, a HasOptional vagy a HasMany metódus használatával megadhatja, hogy az entitás milyen típusú kapcsolatban vesz részt. A HasRequired és a HasOptional metódusok egy lambda kifejezést használnak, amely egy referencianavigációs tulajdonságot jelöl. A HasMany metódus egy lambda kifejezést használ, amely egy gyűjtemény navigációs tulajdonságát jelöli. Ezután konfigurálhat inverz navigációs tulajdonságot a WithRequired, a WithOptional és a WithMany metódusokkal. Ezek a metódusok túlterheléssel rendelkeznek, amelyek nem fogadnak el argumentumokat, és számosság megadására használhatók egyirányú navigációval.
Ezután a HasForeignKey metódussal konfigurálhatja az idegen kulcs tulajdonságait. Ez a metódus egy lambda kifejezést használ, amely az idegen kulcsként használni kívánt tulajdonságot jelöli.
Kötelező és nem kötelező kapcsolat konfigurálása (egy-a-nullához vagy egyhez)
Az alábbi példa egy-a-nullához vagy-egyhez kapcsolatot konfigurál. Az OfficeAssignment rendelkezik az InstructorID tulajdonságával, amely egy elsődleges kulcs és egy idegen kulcs, mivel a tulajdonság neve nem követi azt a konvenciót, amelyet a HasKey metódus használ az elsődleges kulcs konfigurálásához.
// Configure the primary key for the OfficeAssignment
modelBuilder.Entity<OfficeAssignment>()
.HasKey(t => t.InstructorID);
// Map one-to-zero or one relationship
modelBuilder.Entity<OfficeAssignment>()
.HasRequired(t => t.Instructor)
.WithOptional(t => t.OfficeAssignment);
Olyan kapcsolat konfigurálása, amelyben mindkét végpontra szükség van (egy az egyhez)
A legtöbb esetben az Entity Framework képes kikövetkeztetni, hogy melyik típus a függő, és melyik a fő egy kapcsolatban. Ha azonban a kapcsolat mindkét vége kötelező, vagy mindkét fél opcionális, az Entity Framework nem tudja azonosítani a függőt és a tagot. Ha a kapcsolat mindkét vége kötelező, használja a WithRequiredPrincipal vagy a WithRequiredDependent parancsot a HasRequired metódus után. Ha a kapcsolat mindkét vége választható, használja a WithOptionalPrincipal vagy a WithOptionalDependent metódusokat a HasOptional után.
// Configure the primary key for the OfficeAssignment
modelBuilder.Entity<OfficeAssignment>()
.HasKey(t => t.InstructorID);
modelBuilder.Entity<Instructor>()
.HasRequired(t => t.OfficeAssignment)
.WithRequiredPrincipal(t => t.Instructor);
Több-a-többhöz kapcsolat konfigurálása
Az alábbi kód egy több az többhöz kapcsolatot konfigurál a Tanfolyam és az Oktató típusok között. Az alábbi példában az alapértelmezett Code First konvenciók egy kapcsolótáblát hoznak létre. Ennek eredményeként a CourseInstructor tábla Course_CourseID és Instructor_InstructorID oszlopokkal jön létre.
modelBuilder.Entity<Course>()
.HasMany(t => t.Instructors)
.WithMany(t => t.Courses)
Ha meg szeretné adni az illesztőtábla nevét és a tábla oszlopainak nevét, a Map metódussal további konfigurációt kell végeznie. Az alábbi kód a CourseInstructor táblát hozza létre CourseID és InstructorID oszlopokkal.
modelBuilder.Entity<Course>()
.HasMany(t => t.Instructors)
.WithMany(t => t.Courses)
.Map(m =>
{
m.ToTable("CourseInstructor");
m.MapLeftKey("CourseID");
m.MapRightKey("InstructorID");
});
Kapcsolat konfigurálása egy navigációs tulajdonsággal
Az egyirányú (más néven egyirányú) kapcsolat az, amikor a navigációs tulajdonság csak az egyik kapcsolat végén van definiálva, és nem mindkettőn. A Code First szerint a konvenció alapján az egyirányú kapcsolatot mindig egy-a-többhöz értelemben veszik. Ha például egy-egy kapcsolatot kíván létrehozni az Oktató és az OfficeAssignment között, ahol navigációs tulajdonság csak az Oktató típusban van, a kapcsolat konfigurálásához a fluent API-t kell használnia.
// Configure the primary Key for the OfficeAssignment
modelBuilder.Entity<OfficeAssignment>()
.HasKey(t => t.InstructorID);
modelBuilder.Entity<Instructor>()
.HasRequired(t => t.OfficeAssignment)
.WithRequiredPrincipal();
Kaszkád törlés engedélyezése
Egy kapcsolat kaszkádolt törlését a WillCascadeOnDelete metódussal konfigurálhatja. Ha a függő entitás idegen kulcsa nem null értékű, akkor a Code First a kaszkádolt törlést állítja be a kapcsolaton. Ha a függő entitás idegen kulcsa null értéket is felvehet, a Code First nem állítja be a lánctörlést a kapcsolatra, és amikor a fő entitás törlődik, az idegen kulcs null értékűre lesz állítva.
A kaszkádolt törlési konvenciók a következőkkel távolíthatók el:
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()
Az alábbi kód konfigurálja a szükséges kapcsolatot, majd letiltja a kaszkádolt törlést.
modelBuilder.Entity<Course>()
.HasRequired(t => t.Department)
.WithMany(t => t.Courses)
.HasForeignKey(d => d.DepartmentID)
.WillCascadeOnDelete(false);
Összetett idegen kulcs konfigurálása
Ha a Részleg típus elsődleges kulcsa a DepartmentID és a Name tulajdonságokból állt, akkor az alábbiak szerint konfigurálhatja a részleg elsődleges kulcsát és a kurzustípusok idegen kulcsát:
// Composite primary key
modelBuilder.Entity<Department>()
.HasKey(d => new { d.DepartmentID, d.Name });
// Composite foreign key
modelBuilder.Entity<Course>()
.HasRequired(c => c.Department)
.WithMany(d => d.Courses)
.HasForeignKey(d => new { d.DepartmentID, d.DepartmentName });
A modellben nem definiált idegen kulcs átnevezése
Ha úgy dönt, hogy nem határoz meg idegen kulcsot a CLR-típuson, de meg szeretné adni, hogy milyen névvel kell rendelkeznie az adatbázisban, tegye a következőket:
modelBuilder.Entity<Course>()
.HasRequired(c => c.Department)
.WithMany(t => t.Courses)
.Map(m => m.MapKey("ChangedDepartmentID"));
Külső kulcsnév konfigurálása, amely nem követi a kód első konvencióját
Ha a kurzusosztály idegenkulcs-tulajdonságát a DepartmentID helyett SomeDepartmentID-nek nevezik, a következőket kell tennie annak megadásához, hogy a SomeDepartmentID legyen az idegen kulcs:
modelBuilder.Entity<Course>()
.HasRequired(c => c.Department)
.WithMany(d => d.Courses)
.HasForeignKey(c => c.SomeDepartmentID);
Mintákban használt modell
Az alábbi Code First modellt használja a rendszer az oldalon található mintákhoz.
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
// add a reference to System.ComponentModel.DataAnnotations DLL
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System;
public class SchoolEntities : DbContext
{
public DbSet<Course> Courses { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure Code First to ignore PluralizingTableName convention
// If you keep this convention then the generated tables will have pluralized names.
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
public class Department
{
public Department()
{
this.Courses = new HashSet<Course>();
}
// Primary key
public int DepartmentID { get; set; }
public string Name { get; set; }
public decimal Budget { get; set; }
public System.DateTime StartDate { get; set; }
public int? Administrator { get; set; }
// Navigation property
public virtual ICollection<Course> Courses { get; private set; }
}
public class Course
{
public Course()
{
this.Instructors = new HashSet<Instructor>();
}
// Primary key
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
// Foreign key
public int DepartmentID { get; set; }
// Navigation properties
public virtual Department Department { get; set; }
public virtual ICollection<Instructor> Instructors { get; private set; }
}
public partial class OnlineCourse : Course
{
public string URL { get; set; }
}
public partial class OnsiteCourse : Course
{
public OnsiteCourse()
{
Details = new Details();
}
public Details Details { get; set; }
}
public class Details
{
public System.DateTime Time { get; set; }
public string Location { get; set; }
public string Days { get; set; }
}
public class Instructor
{
public Instructor()
{
this.Courses = new List<Course>();
}
// Primary key
public int InstructorID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public System.DateTime HireDate { get; set; }
// Navigation properties
public virtual ICollection<Course> Courses { get; private set; }
}
public class OfficeAssignment
{
// Specifying InstructorID as a primary
[Key()]
public Int32 InstructorID { get; set; }
public string Location { get; set; }
// When Entity Framework sees Timestamp attribute
// it configures ConcurrencyCheck and DatabaseGeneratedPattern=Computed.
[Timestamp]
public Byte[] Timestamp { get; set; }
// Navigation property
public virtual Instructor Instructor { get; set; }
}