Árnyék- és indexelőtulajdonságok

Az árnyéktulajdonságok olyan tulajdonságok, amelyek nincsenek definiálva a .NET-entitásosztályban, de az EF Core-modellben az adott entitástípushoz vannak definiálva. Ezeknek a tulajdonságoknak az értéke és állapota kizárólag a Change Trackerben marad fenn. Az árnyéktulajdonságok akkor hasznosak, ha az adatbázisban olyan adatok találhatók, amelyeket nem szabad a leképezett entitástípusokon elérhetővé tenni.

Az indexelő tulajdonságai entitástípus-tulajdonságok, amelyek mögött egy indexelő áll a .NET entitásosztályban. Ezek az indexelővel érhetők el a .NET-osztálypéldányokon. Emellett további tulajdonságok hozzáadását is lehetővé teszi az entitástípushoz a CLR-osztály módosítása nélkül.

Idegen kulcs árnyéktulajdonságai

Az árnyéktulajdonságokat leggyakrabban idegen kulcstulajdonságokhoz használják, ahol konvenció szerint hozzáadják őket a modellhez, ha nem található idegenkulcs-tulajdonság konvenció vagy explicit módon konfigurálva. A kapcsolatot navigációs tulajdonságok jelölik, de az adatbázisban egy idegenkulcs-korlátozás kényszeríti, és az idegen kulcs oszlopának értéke a megfelelő árnyéktulajdonságban van tárolva.

A tulajdonság neve el lesz nevezve <navigation property name><principal key property name> (az elnevezéshez a függő entitáson a fő entitásra mutató navigációt használjuk). Ha a fő kulcs tulajdonság neve a navigációs tulajdonság nevével kezdődik, akkor a név csak az lesz <principal key property name>. Ha a függő entitáson nincs navigációs tulajdonság, akkor a rendszer az elsődleges vagy másodlagos kulcs tulajdonságnévvel összefűzött egyszerű típusnevet használja a helyén <principal type name><principal key property name>.

A következő kódlista például egy BlogId árnyéktulajdonság bevezetését eredményezi az Post entitásban:

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    // Since there is no CLR property which holds the foreign
    // key for this relationship, a shadow property is created.
    public Blog Blog { get; set; }
}

Árnyéktulajdonságok konfigurálása

Az árnyéktulajdonságok konfigurálásához használhatja a Fluent API-t . Miután meghívta a sztring túlterhelését Property<TProperty>(String), a többi tulajdonsághoz tartozó konfigurációs hívásokat láncba helyezheti. A következő példában, mivel a Blog-nek nincs olyan CLR-tulajdonsága, amelynek neve LastUpdated, létrejön egy árnyéktulajdonság.

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property<DateTime>("LastUpdated");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Ha a Property metódushoz megadott név megegyezik egy meglévő tulajdonság nevével (egy árnyéktulajdonság vagy egy entitásosztályban definiált tulajdonság), akkor a kód az új árnyéktulajdonság bevezetése helyett konfigurálja a meglévő tulajdonságot.

Árnyéktulajdonságok elérése

Az árnyéktulajdonság-értékek az API-val ChangeTracker szerezhetők be és módosíthatók:

context.Entry(myBlog).Property("LastUpdated").CurrentValue = DateTime.Now;

Az árnyéktulajdonságok a LINQ-lekérdezésekben a EF.Property statikus módszerrel hivatkozhatók:

var blogs = context.Blogs
    .OrderBy(b => EF.Property<DateTime>(b, "LastUpdated"));

Az árnyéktulajdonságok nem érhetők el nyomkövetés nélküli lekérdezés után, mivel a visszaadott entitásokat a változáskövető nem követi nyomon.

Indexelő tulajdonságainak konfigurálása

Az indexelő tulajdonságainak konfigurálásához használhatja a Fluent API-t. Miután meghívta a metódust IndexerProperty, a többi tulajdonsághoz tartozó konfigurációs hívások bármelyikét láncba kapcsolhatja. Az alábbi példában egy indexelő van definiálva, Blog és egy indexelőtulajdonság létrehozásához lesz használva.

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>().IndexerProperty<DateTime>("LastUpdated");
    }
}

public class Blog
{
    private readonly Dictionary<string, object> _data = new Dictionary<string, object>();
    public int BlogId { get; set; }

    public object this[string key]
    {
        get => _data[key];
        set => _data[key] = value;
    }
}

Ha a IndexerProperty metódushoz megadott név megegyezik egy meglévő indexelőtulajdonság nevével, akkor a kód konfigurálja a meglévő tulajdonságot. Ha az entitástípus rendelkezik egy tulajdonsággal, amelyet az entitásosztály egyik tulajdonsága biztosít, akkor kivétel történik, mivel az indexelő tulajdonságait csak az indexelőn keresztül lehet elérni.

Az indexelő tulajdonságai a LINQ-lekérdezésekben a EF.Property fent látható statikus módszerrel vagy a CLR indexelő tulajdonság használatával hivatkozhatók.

Tulajdonságcsomag entitástípusai

Az olyan entitástípusok, amelyek csak indexelőtulajdonságokat tartalmaznak, tulajdonságcsomag-entitástípusokként ismertek. Ezek az entitástípusok nem rendelkeznek árnyéktulajdonságokkal, és az EF inkább indexelő tulajdonságokat hoz létre. Jelenleg csak Dictionary<string, object> tulajdonságcsomag entitástípusként támogatott. Ezt egy egyedi névvel rendelkező megosztott típusú entitástípusként kell konfigurálni, és a megfelelő DbSet tulajdonságot hívással Set kell implementálni.

internal class MyContext : DbContext
{
    public DbSet<Dictionary<string, object>> Blogs => Set<Dictionary<string, object>>("Blog");

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.SharedTypeEntity<Dictionary<string, object>>(
            "Blog", bb =>
            {
                bb.Property<int>("BlogId");
                bb.Property<string>("Url");
                bb.Property<DateTime>("LastUpdated");
            });
    }
}

A tulajdonságcsomag-entitástípusok akkor használhatók, ha normál entitástípust használnak, beleértve a saját entitástípust is. Vannak azonban bizonyos korlátaik: