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.
Paraméterekkel rendelkező konstruktor definiálható, és az EF Core meghívja ezt a konstruktort az entitás egy példányának létrehozásakor. A konstruktorparaméterek hozzárendelhetők megadott tulajdonságokhoz vagy különböző szolgáltatásokhoz, hogy megkönnyítsék az olyan viselkedéseket, mint például a lusta betöltés.
Megjegyzés:
Jelenleg minden konstruktorkötés konvenció szerint történik. Az egyes konstruktorok konfigurálását egy későbbi kiadásra tervezik.
Kötés leképezett tulajdonságokra
Vegyünk egy tipikus Blog/Post modellt:
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public ICollection<Post> Posts { get; } = new List<Post>();
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime PostedOn { get; set; }
public Blog Blog { get; set; }
}
Amikor az EF Core ilyen típusú példányokat hoz létre, például egy lekérdezés eredményeihez, először meghívja az alapértelmezett paraméter nélküli konstruktort, majd minden tulajdonságot az adatbázisból származó értékre állít be. Ha azonban az EF Core talál egy paraméteres konstruktort, amelynek paraméterneve és típusa megegyezik a megfeleltetett tulajdonságokéval, akkor a paraméteres konstruktort az adott tulajdonságok értékeivel hívja meg, és nem állítja be kifejezetten az egyes tulajdonságokat. Például:
public class Blog
{
public Blog(int id, string name, string author)
{
Id = id;
Name = name;
Author = author;
}
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public ICollection<Post> Posts { get; } = new List<Post>();
}
public class Post
{
public Post(int id, string title, DateTime postedOn)
{
Id = id;
Title = title;
PostedOn = postedOn;
}
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime PostedOn { get; set; }
public Blog Blog { get; set; }
}
Néhány megjegyzés:
- Nem minden tulajdonságnak kell konstruktorparaméterekkel rendelkeznie. A Post.Content tulajdonságot például egyetlen konstruktorparaméter sem állítja be, ezért az EF Core a konstruktor normál meghívása után állítja be.
- A paramétertípusoknak és a neveknek meg kell egyezniük a tulajdonságtípusokkal és a nevekkel, kivéve, hogy a tulajdonságok Pascal-stílusúak lehetnek, míg a paraméterek camelCase-stílusban vannak.
- Az EF Core nem tudja konstruktor használatával beállítani a navigációs tulajdonságokat (például a blogot vagy a bejegyzéseket).
- A konstruktor lehet nyilvános, privát, vagy bármilyen más hozzáférhetőségű. A lusta betöltési proxyk azonban megkövetelik, hogy a konstruktor elérhető legyen az öröklő proxyosztály számára. Ez általában azt jelenti, hogy nyilvánossá vagy védetté teheti.
Csak olvasható tulajdonságok
Ha a tulajdonságokat a konstruktoron keresztül állítja be, érdemes lehet néhányat csak olvashatóvá tenni. Az EF Core ezt támogatja, de van néhány dolog, amire érdemes figyelni:
- A beállító nélküli tulajdonságok nem konvenció szerint vannak leképezve. (Ez általában olyan tulajdonságok leképezésére szolgál, amelyeket nem szabad leképezni, például a számított tulajdonságokat.)
- Az automatikusan generált kulcsértékek használatához olvasási-írási kulcstulajdonság szükséges, mivel a kulcs értékét a kulcsgenerátornak kell beállítania új entitások beszúrásakor.
Ezek elkerülésének egy egyszerű módja a privát beállítók használata. Például:
public class Blog
{
public Blog(int id, string name, string author)
{
Id = id;
Name = name;
Author = author;
}
public int Id { get; private set; }
public string Name { get; private set; }
public string Author { get; private set; }
public ICollection<Post> Posts { get; } = new List<Post>();
}
public class Post
{
public Post(int id, string title, DateTime postedOn)
{
Id = id;
Title = title;
PostedOn = postedOn;
}
public int Id { get; private set; }
public string Title { get; private set; }
public string Content { get; set; }
public DateTime PostedOn { get; private set; }
public Blog Blog { get; set; }
}
Az EF Core egy privát setterrel rendelkező tulajdonságot olvasható-írhatónak tekint, ami azt jelenti, hogy minden tulajdonság ugyanúgy van leképezve, mint korábban, és a kulcs továbbra is az adatbázis által generált lehet.
A privát setterek használatának alternatíva, ha a tulajdonságokat csak olvashatóvá teszi, és explicitebb leképezést ad hozzá az OnModelCreatingben. Ugyanígy egyes tulajdonságok teljesen eltávolíthatók, és csak mezőkre cserélhetők. Vegyük például az alábbi entitástípusokat:
public class Blog
{
private int _id;
public Blog(string name, string author)
{
Name = name;
Author = author;
}
public string Name { get; }
public string Author { get; }
public ICollection<Post> Posts { get; } = new List<Post>();
}
public class Post
{
private int _id;
public Post(string title, DateTime postedOn)
{
Title = title;
PostedOn = postedOn;
}
public string Title { get; }
public string Content { get; set; }
public DateTime PostedOn { get; }
public Blog Blog { get; set; }
}
És ez a konfiguráció az OnModelCreatingben:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>(
b =>
{
b.HasKey("_id");
b.Property(e => e.Author);
b.Property(e => e.Name);
});
modelBuilder.Entity<Post>(
b =>
{
b.HasKey("_id");
b.Property(e => e.Title);
b.Property(e => e.PostedOn);
});
}
Figyelembe veendő szempontok:
- A kulcs "tulajdonsága" most már mező. Ez nem egy
readonlymező, így a tároló által generált kulcsok használhatók. - A többi tulajdonság írásvédett, és csak a konstruktorban lehet beállítani.
- Ha az elsődleges kulcs értékét csak az EF állítja be vagy olvassa be az adatbázisból, akkor nem kell belefoglalnia a konstruktorba. Így a kulcs "tulajdonsága" egyszerű mezőként marad, és egyértelművé teszi, hogy nem szabad explicit módon beállítani új blogok vagy bejegyzések létrehozásakor.
Megjegyzés:
Ez a kód a fordító "169" figyelmeztetését fogja eredményezni, amely azt jelzi, hogy a mező soha nem lesz használatban. Ez figyelmen kívül hagyható, mivel a valóságban az EF Core extralinguisztikus módon használja a mezőt.
Szolgáltatások injektálása
Az EF Core a "szolgáltatásokat" is injektálhatja egy entitástípus konstruktorába. Például a következők injektálhatók:
-
DbContext- az aktuális kontextus példány, amelynek típusa lehet a származtatott DbContext típus is -
ILazyLoader- a lazy-loading szolgáltatás - további részletekért tekintse meg a lazy-loading dokumentációt - késleltetett betöltésű helyettesítő – további részletekért tekintse meg a késleltetett betöltési (lazy-loading) dokumentációt . -
IEntityType- az ehhez az entitástípushoz társított EF Core-metaadatok
Megjegyzés:
Jelenleg csak az EF Core által ismert szolgáltatások injektálhatók. Az alkalmazásszolgáltatások injektálásának támogatása a jövőbeni kiadásban is meg van fontolva.
Az injektált DbContext például az adatbázis szelektív elérésére használható, hogy a kapcsolódó entitásokra vonatkozó információkat az összes betöltése nélkül szerezze be. Az alábbi példában ez a blog bejegyzéseinek számának lekérésére szolgál a bejegyzések betöltése nélkül:
public class Blog
{
public Blog()
{
}
private Blog(BloggingContext context)
{
Context = context;
}
private BloggingContext Context { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public ICollection<Post> Posts { get; set; }
public int PostsCount
=> Posts?.Count
?? Context?.Set<Post>().Count(p => Id == EF.Property<int?>(p, "BlogId"))
?? 0;
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime PostedOn { get; set; }
public Blog Blog { get; set; }
}
Néhány dolog, amit észre kell venni erről:
- A konstruktor privát, mivel csak az EF Core hívja, és létezik egy másik nyilvános konstruktor, amely általános használatra készült.
- Az injektált szolgáltatást (vagyis a környezetet) használó kód védekezik az
nullolyan esetek kezelésére, amikor az EF Core nem hozza létre a példányt. - Mivel a szolgáltatás egy olvasható/írható tulajdonságban van tárolva, az entitás visszaáll, amikor egy új környezetpéldányhoz csatlakozik.
Figyelmeztetés
A DbContext ilyen injektálása gyakran antimintának számít, mivel közvetlenül az EF Core-hoz párosítja az entitástípusokat. A szolgáltatásinjektálás használata előtt gondosan fontolja meg az összes lehetőséget.