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.
Az Entity Framework Code First használata során az alapértelmezett viselkedés az, hogy a POCO-osztályokat táblákra térképezi fel az EF beépített konvencióinak készletével. Néha azonban nem tudja vagy nem szeretné követni ezeket a konvenciókat, és az entitásokat máshoz kell hozzárendelnie, mint amit a konvenciók diktálnak.
Az EF konfigurálásának két fő módja van, hogy a konvencióktól eltérőt használjon, nevezetesen a széljegyzeteket vagy az EFs fluent API-t. A széljegyzetek csak a fluent API-funkciók egy részhalmazára vonatkoznak, ezért vannak olyan leképezési forgatókönyvek, amelyek nem érhetők el széljegyzetekkel. Ez a cikk bemutatja, hogyan konfigurálhatja a fluent API-t a tulajdonságok konfigurálásához.
A kód első fluent API-ja leggyakrabban az OnModelCreating metódus felülbírálásával érhető el a származtatott DbContexten. Az alábbi minták bemutatják, hogyan végezhet különböző feladatokat a fluent API-val, és hogyan másolhatja ki és szabhatja testre a kódot a modellnek megfelelően, ha azt a modellt szeretné látni, amelyet a as-is használhat, akkor a cikk végén lesz megadva.
Model-szintű beállítások
Alapértelmezett séma (EF6-tól)
Az EF6-tól kezdve a DbModelBuilder HasDefaultSchema metódusával megadhatja az összes tábla, tárolt eljárás stb. számára használandó adatbázissémát. Ez az alapértelmezett beállítás felül lesz bírálva minden olyan objektum esetében, amelyhez explicit módon konfigurál egy másik sémát.
modelBuilder.HasDefaultSchema("sales");
Egyéni konvenciók (EF6 és újabb)
Az EF6-tól kezdve létrehozhatja saját konvencióit, hogy kiegészítse a Code Firstben szereplőket. További részletekért tekintse meg az Egyéni kód első konvencióit.
Tulajdonságleképezés
A tulajdonságmetódus egy entitáshoz vagy összetett típushoz tartozó minden tulajdonság attribútumainak konfigurálására szolgál. A tulajdonságmetódus egy adott tulajdonság konfigurációs objektumának lekérésére szolgál. A konfigurációs objektum beállításai a konfigurált típusra vonatkoznak; Az IsUnicode például csak sztringtulajdonságokon érhető el.
Elsődleges kulcs konfigurálása
Az elsődleges kulcsokra vonatkozó Entity Framework-konvenció a következő:
- Az osztály meghatároz egy tulajdonságot, amelynek neve "ID" vagy "Id"
- vagy egy osztálynév, amelyet az „ID” vagy az „Id” követ
Ha egy tulajdonságot kifejezetten elsődleges kulcsként szeretne beállítani, használhatja a HasKey metódust. Az alábbi példában a HasKey metódussal konfigurálható az InstructorID elsődleges kulcs az OfficeAssignment típuson.
modelBuilder.Entity<OfficeAssignment>().HasKey(t => t.InstructorID);
Összetett elsődleges kulcs konfigurálása
Az alábbi példa a Részlegazonosító és a Név tulajdonságokat állítja be a részlegtípus összetett elsődleges kulcsának.
modelBuilder.Entity<Department>().HasKey(t => new { t.DepartmentID, t.Name });
A numerikus elsődleges kulcsok identitásának kikapcsolása
Az alábbi példa a DepartmentID tulajdonságot System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None értékre állítja, amely azt jelzi, hogy az adatbázis nem hozza létre az értéket.
modelBuilder.Entity<Department>().Property(t => t.DepartmentID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
A tulajdonság maximális hosszának megadása
Az alábbi példában a Név tulajdonság legfeljebb 50 karakter hosszúságú lehet. Ha 50 karakternél hosszabb értéket ad meg, a DbEntityValidationException kivételt kap. Ha a Code First létrehoz egy adatbázist ebből a modellből, a Név oszlop maximális hosszát is 50 karakterre állítja.
modelBuilder.Entity<Department>().Property(t => t.Name).HasMaxLength(50);
A tulajdonság kötelezőként való konfigurálása
Az alábbi példában a Név tulajdonságra van szükség. Ha nem adja meg a nevet, kap egy DbEntityValidationException kivételt. Ha a Code First létrehoz egy adatbázist ebből a modellből, akkor a tulajdonság tárolására használt oszlop általában nem null értékű lesz.
Megjegyzés:
Bizonyos esetekben előfordulhat, hogy az adatbázis oszlopa nem lehet null értékű, még akkor sem, ha a tulajdonság megadása kötelező. Ha például több típushoz használ TPH öröklési stratégiai adatokat, a rendszer egyetlen táblában tárolja. Ha egy származtatott típus tartalmaz egy kötelező tulajdonságot, az oszlop nem tehető nem null értékűvé, mivel a hierarchia nem minden típusának lesz ez a tulajdonsága.
modelBuilder.Entity<Department>().Property(t => t.Name).IsRequired();
Index konfigurálása egy vagy több tulajdonságon
Megjegyzés:
CSAK EF6.1 – Az Index attribútum az Entity Framework 6.1-ben lett bevezetve. Ha korábbi verziót használ, az ebben a szakaszban szereplő információk nem érvényesek.
Az indexek létrehozását a Fluent API nem támogatja natív módon, de a Fluent API-n keresztül használhatja az IndexAttribute támogatását. Az indexattribútumokat úgy dolgozzák fel, hogy belefognak egy modelljegyzetet a modellbe, amely ezután indexké alakul az adatbázisban a folyamat későbbi részében. Ezeket a megjegyzéseket manuálisan is hozzáadhatja a Fluent API-val.
Ennek legegyszerűbb módja az IndexAttribute egy olyan példányának létrehozása, amely az új index összes beállítását tartalmazza. Ezután létrehozhatja az IndexAnnotation egy példányát , amely egy EF-specifikus típus, amely az IndexAttribute beállításokat modelljegyzetgé alakítja, amely az EF-modellben tárolható. Ezek ezután átadhatók a Fluent API HasColumnAnnotation metódusának, megadva a széljegyzet indexének nevét.
modelBuilder
.Entity<Department>()
.Property(t => t.Name)
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute()));
Az IndexAttribute szolgáltatásban elérhető beállítások teljes listáját a Code First Data AnnotationsIndex szakaszában találja. Ez magában foglalja az index nevének testreszabását, az egyedi indexek létrehozását és a többoszlopos indexek létrehozását.
Egyetlen tulajdonságon több indexjegyzetet is megadhat, ha egy IndexAttribute tömböt ad át az IndexAnnotation konstruktorának.
modelBuilder
.Entity<Department>()
.Property(t => t.Name)
.HasColumnAnnotation(
"Index",
new IndexAnnotation(new[]
{
new IndexAttribute("Index1"),
new IndexAttribute("Index2") { IsUnique = true }
})));
Annak meghatározása, hogy a CLR-tulajdonság ne legyen leképezve az adatbázis egy oszlopára.
Az alábbi példa bemutatja, hogyan adhatja meg, hogy egy CLR-típus egyik tulajdonsága ne legyen leképezve az adatbázis egyik oszlopára.
modelBuilder.Entity<Department>().Ignore(t => t.Budget);
CLR-tulajdonság leképezése egy adott oszlopra az adatbázisban
Az alábbi példa a Name CLR tulajdonságot a DepartmentName adatbázis oszlopra képezi le.
modelBuilder.Entity<Department>()
.Property(t => t.Name)
.HasColumnName("DepartmentName");
A modellben nem definiált idegen kulcs átnevezése
Ha úgy dönt, hogy nem határoz meg idegen kulcsot egy 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"));
Annak konfigurálása, hogy egy sztringtulajdonság támogatja-e a Unicode-tartalmat
Alapértelmezés szerint a karakterláncok Unicode, nvarchar az SQL Serverben. Az IsUnicode metódussal megadhatja, hogy egy sztringnek varchar típusúnak kell lennie.
modelBuilder.Entity<Department>()
.Property(t => t.Name)
.IsUnicode(false);
Adatbázisoszlop adattípusának konfigurálása
A HasColumnType metódus lehetővé teszi az azonos alaptípusú különböző reprezentációk leképezését. Ennek a módszernek a használata nem teszi lehetővé az adatok konvertálását futásidőben. Vegye figyelembe, hogy az IsUnicode az oszlopok varcharra való beállításának előnyben részesített módja, mivel adatbázis-agnosztikus.
modelBuilder.Entity<Department>()
.Property(p => p.Name)
.HasColumnType("varchar");
Tulajdonságok konfigurálása összetett típuson
A skaláris tulajdonságokat kétféleképpen konfigurálhatja egy összetett típuson.
A ComplexTypeConfiguration tulajdonság meghívható.
modelBuilder.ComplexType<Details>()
.Property(t => t.Location)
.HasMaxLength(20);
A pont jelöléssel egy összetett típusú tulajdonsághoz is hozzáférhet.
modelBuilder.Entity<OnsiteCourse>()
.Property(t => t.Details.Location)
.HasMaxLength(20);
Optimista párhuzamossági vezérlőként használandó tulajdonság konfigurálása
Ha meg szeretné adni, hogy egy entitás egy tulajdonsága egyidejűségi jogkivonatot jelöljön, használhatja a ConcurrencyCheck attribútumot vagy az IsConcurrencyToken metódust.
modelBuilder.Entity<OfficeAssignment>()
.Property(t => t.Timestamp)
.IsConcurrencyToken();
Az IsRowVersion metódussal is konfigurálhatja a tulajdonságot sorverzióként az adatbázisban. Ha a tulajdonságot sorverzióra állítja, az automatikusan optimista párhuzamossági jelzőként lesz konfigurálva.
modelBuilder.Entity<OfficeAssignment>()
.Property(t => t.Timestamp)
.IsRowVersion();
Típusleképezés
Annak megadása, hogy egy osztály összetett típus-e
Konvenció szerint a megadott elsődleges kulcs nélküli típus összetett típusként lesz kezelve. Vannak olyan esetek, amikor a Code First nem észlel egy összetett típust (például ha van azonosító nevű tulajdonsága, de nem azt jelenti, hogy elsődleges kulcs). Ilyen esetekben a fluent API használatával explicit módon megadhatja, hogy egy típus összetett típus-e.
modelBuilder.ComplexType<Details>();
Annak megadása, hogy a CLR-entitástípus ne kerüljön leképezésre egy adatbázistáblára.
Az alábbi példa bemutatja, hogyan zárhat ki egy CLR-típust abból, hogy az adatbázis tábláihoz legyen leképezve.
modelBuilder.Ignore<OnlineCourse>();
Entitástípus hozzárendelése egy adott táblához az adatbázisban
A részleg minden tulajdonsága a t_ Részleg nevű tábla oszlopaihoz lesz leképezve.
modelBuilder.Entity<Department>()
.ToTable("t_Department");
A séma nevét a következőképpen is megadhatja:
modelBuilder.Entity<Department>()
.ToTable("t_Department", "school");
A Table-Per-Hierarchy (TPH) öröklésének leképezése
A TPH-leképezési forgatókönyvben az öröklési hierarchiában lévő összes típus egyetlen táblára van leképezve. A rendszer egy diszkriminatív oszlopot használ az egyes sorok típusának azonosítására. Amikor a modellt a Code First használatával hozza létre, a TPH az alapértelmezett stratégia az öröklési hierarchiában részt vevő típusok számára. Alapértelmezés szerint a rendszer hozzáadja a diszkriminatív oszlopot a táblához a "Diszkriminatív" névvel, a hierarchia egyes típusainak CLR-típusnevét pedig a rendszer a diszkriminatív értékekhez használja. Az alapértelmezett viselkedést a fluent API használatával módosíthatja.
modelBuilder.Entity<Course>()
.Map<Course>(m => m.Requires("Type").HasValue("Course"))
.Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));
A Table-Per-Type (TPT) öröklésének leképezése
A TPT-leképezési forgatókönyvben a rendszer minden típust az egyes táblákhoz rendel. A kizárólag alaptípushoz vagy származtatott típushoz tartozó tulajdonságok egy olyan táblában vannak tárolva, amely megfelel az adott típusnak. A származtatott típusok leképezésére szolgáló táblák egy idegen kulcsot is tárolnak, amely a származtatott táblát az alaptáblával összekapcsolja.
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");
A Table-Per-Concrete Class (TPC) öröklésének leképezése
A TPC-leképezési forgatókönyvben a hierarchia összes nem absztrakt típusa egyedi táblákra van leképezve. A származtatott osztályokra leképezett tábláknak nincs kapcsolata az adatbázis alaposztályához leképezett táblával. Az osztály minden tulajdonsága, beleértve az örökölt tulajdonságokat is, a megfelelő tábla oszlopaihoz van megfeleltetve.
Az egyes származtatott típusok konfigurálásához hívja meg a MapInheritedProperties metódust. A MapInheritedProperties újraképezi az alaposztálytól örökölt összes tulajdonságot a származtatott osztály táblájának új oszlopaiba.
Megjegyzés:
Vegye figyelembe, hogy mivel a TPC öröklési hierarchiájában részt vevő táblák nem osztanak meg elsődleges kulcsot, ismétlődő entitáskulcsok lesznek beszúrva az alosztályokra leképezett táblákba, ha az adatbázis által létrehozott értékek azonos identitásmaggal rendelkeznek. A probléma megoldásához megadhat egy másik kezdőértéket az egyes táblákhoz, vagy kikapcsolhatja az identitást az elsődleges kulcs tulajdonságában. A Code First használatakor az identitás az egész szám kulcstulajdonságainak alapértelmezett értéke.
modelBuilder.Entity<Course>()
.Property(c => c.CourseID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<OnsiteCourse>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("OnsiteCourse");
});
modelBuilder.Entity<OnlineCourse>().Map(m =>
{
m.MapInheritedProperties();
m.ToTable("OnlineCourse");
});
Egy entitástípus tulajdonságainak leképezése az adatbázis több táblájára (entitás felosztása)
Az entitások felosztása lehetővé teszi egy entitástípus tulajdonságainak több táblára való elosztását. A következő példában a Részleg entitás két táblára oszlik: Részleg és RészlegRészletek. Az entitások felosztása a Map metódus több hívását használja a tulajdonságok egy részhalmazának egy adott táblához való leképezéséhez.
modelBuilder.Entity<Department>()
.Map(m =>
{
m.Properties(t => new { t.DepartmentID, t.Name });
m.ToTable("Department");
})
.Map(m =>
{
m.Properties(t => new { t.DepartmentID, t.Administrator, t.StartDate, t.Budget });
m.ToTable("DepartmentDetails");
});
Több entitástípus hozzárendelése egy táblához az adatbázisban (táblafelosztás)
Az alábbi példa két olyan entitástípust képez le, amelyek egy elsődleges kulcsot használnak egy táblához.
modelBuilder.Entity<OfficeAssignment>()
.HasKey(t => t.InstructorID);
modelBuilder.Entity<Instructor>()
.HasRequired(t => t.OfficeAssignment)
.WithRequiredPrincipal(t => t.Instructor);
modelBuilder.Entity<Instructor>().ToTable("Instructor");
modelBuilder.Entity<OfficeAssignment>().ToTable("Instructor");
Entitástípus leképezése tárolt eljárások beszúrására/frissítésére/törlésére (EF6-tól)
Az EF6-tól kezdve leképezhet egy entitást tárolt eljárások használatára a beszúráshoz, frissítéshez és törléshez. Lásd további részletekért a Code First Insert/Update/Delete Tárolt eljárások című részt.
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; }
}