Megosztás a következőn keresztül:


Nyomon követés és No-Tracking lekérdezések

Az Entity Framework Core nyomon követési viselkedése meghatározza, hogy a rendszer tárolja-e az entitáspéldány adatait a változáskövetőben. Ha egy entitást nyomon követnek, az entitásban észlelt módosítások megmaradnak az adatbázisban a folyamat során SaveChanges. Az EF Core emellett javítja a navigációs tulajdonságokat a nyomkövetési lekérdezés eredményében szereplő entitások és a változáskövetésben szereplő entitások között.

Megjegyzés:

A kulcs nélküli entitástípusok soha nem lesznek nyomon követve. Ahol ez a cikk entitástípusokat említ, olyan entitástípusokra hivatkozik, amelyek kulcsként vannak meghatározva.

Jótanács

A cikk mintáját a GitHubon tekintheti meg.

Lekérdezések nyomon követése

Alapértelmezés szerint azok a lekérdezések követnek, amelyek entitástípusokat adnak vissza. A nyomkövetési lekérdezések azt jelentik, hogy az entitáspéldányok módosításait SaveChangesa rendszer megőrzi. Az alábbi példában a rendszer észleli és megőrzi a blogok minősítésének módosítását az adatbázison a következő időszakban SaveChanges:

var blog = await context.Blogs.SingleOrDefaultAsync(b => b.BlogId == 1);
blog.Rating = 5;
await context.SaveChangesAsync();

Ha az eredmények egy nyomkövetési lekérdezésben jelennek meg, az EF Core ellenőrzi, hogy az entitás már szerepel-e a környezetben. Ha az EF Core talál egy meglévő entitást, akkor ugyanazt a példányt adja vissza, amely valószínűleg kevesebb memóriát használ, és gyorsabb, mint egy nyomkövetés nélküli lekérdezés. Az EF Core nem írja felül az entitás tulajdonságainak aktuális és eredeti értékeit az adatbázisértékekkel rendelkező bejegyzésben. Ha az entitás nem található a környezetben, az EF Core létrehoz egy új entitáspéldányt, és csatolja azt a környezethez. A lekérdezés eredményei nem tartalmaznak olyan entitást, amely hozzáadva van a környezethez, de még nem mentve az adatbázisba.

Nyomkövetés nélküli lekérdezések

A nem követett lekérdezések hasznosak, ha az eredményeket csak olvasható környezetben használják. Általában gyorsabbak a végrehajtásuk, mert nincs szükség a változáskövetési adatok beállítására. Ha az adatbázisból lekért entitásokat nem kell frissíteni, akkor nem követési lekérdezést kell használni. Az egyes lekérdezések beállíthatók nyomkövetés nélkülinek. A nyomkövetés nélküli lekérdezések az adatbázisban található adatok alapján is eredményt adnak, figyelmen kívül hagyva a helyi módosításokat vagy a hozzáadott entitásokat.

var blogs = await context.Blogs
    .AsNoTracking()
    .ToListAsync();

Az alapértelmezett nyomkövetési viselkedés a környezeti példány szintjén módosítható:

context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

var blogs = await context.Blogs.ToListAsync();

A következő szakasz azt ismerteti, hogy a nyomkövetés nélküli lekérdezések mikor lehetnek kevésbé hatékonyak, mint a nyomkövetési lekérdezések.

Identitásfeloldás

Mivel a nyomkövetési lekérdezések a változáskövetőt használják, az EF Core identitásfeloldásokat végez egy követő lekérdezésben. Egy entitás materializálásakor az EF Core ugyanazt az entitáspéldányt adja vissza a változáskövetőből, ha az már követés alatt áll. Ha az eredmény többször is ugyanazt az entitást tartalmazza, a függvény minden előforduláshoz ugyanazt a példányt adja vissza. Nyomkövetés nélküli lekérdezések

  • Ne használja a változáskövetőt, és ne végezze el az identitásfeloldásokat.
  • Az entitás új példányát adja vissza akkor is, ha ugyanazt az entitást többször is tartalmazza az eredmény.

A nyomon követés és a nem nyomon követés kombinálható ugyanabban a lekérdezésben. Ez azt jelenti, hogy rendelkezhet nyomkövetés nélküli lekérdezéssel, amely identitásfeloldásokat végez az eredményekben. A lekérdezhető operátorhoz hasonlóan AsNoTracking egy másik operátort AsNoTrackingWithIdentityResolution<TEntity>(IQueryable<TEntity>)is hozzáadtunk. Az enumeráláshoz QueryTrackingBehavior hozzá van adva egy társított bejegyzés is. Ha az identitásfeloldási lekérdezés nyomkövetés nélkül van konfigurálva, a lekérdezési eredmények létrehozásakor a háttérben különálló változáskövetőt használ a rendszer, így az egyes példányok csak egyszer lesznek materializálva. Mivel ez a változáskövető eltér a környezetben lévőtől, az eredményeket nem követi nyomon a környezet. A lekérdezés teljes számbavétele után a változáskövető kikerül a hatókörből, és szükség szerint összegyűjti a szemetet.

var blogs = await context.Blogs
    .AsNoTrackingWithIdentityResolution()
    .ToListAsync();

Az alapértelmezett nyomkövetési viselkedés konfigurálása

Ha úgy találja, hogy sok lekérdezés nyomkövetési viselkedését módosítja, érdemes lehet inkább az alapértelmezettet módosítania:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying.Tracking;Trusted_Connection=True;ConnectRetryCount=0")
        .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}

Így az összes lekérdezés alapértelmezés szerint nem lesz nyomon követve. A konkrét lekérdezések nyomon követéséhez továbbra is hozzáadhatja a AsTracking-t.

Nyomon követés és egyéni előrejelzések

Még akkor is, ha a lekérdezés eredménytípusa nem entitástípus, az EF Core alapértelmezés szerint továbbra is nyomon követi az eredményben szereplő entitástípusokat. Az alábbi lekérdezésben, amely névtelen típust ad vissza, a rendszer nyomon követi az eredményhalmaz példányait Blog .

var blog = context.Blogs
    .Select(
        b =>
            new { Blog = b, PostCount = b.Posts.Count() });

Ha az eredményhalmaz olyan entitástípusokat tartalmaz, amelyek a LINQ-összetételből származnak, az EF Core nyomon követi őket.

var blog = context.Blogs
    .Select(
        b =>
            new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });

Ha az eredményhalmaz nem tartalmaz entitástípusokat, akkor nem történik nyomkövetés. A következő lekérdezésben egy névtelen típust adunk vissza az entitás néhány értékével (de a tényleges entitástípus példányai nem). A lekérdezésből nincsenek nyomon követett entitások.

var blog = context.Blogs
    .Select(
        b =>
            new { Id = b.BlogId, b.Url });

Az EF Core támogatja az ügyfelek kiértékelését a legfelső szintű előrejelzésben. Ha az EF Core egy entitáspéldányt hoz létre az ügyfélértékeléshez, az nyomon lesz követve. Itt, mivel blog entitásokat adunk át az ügyfél metódusnak StandardizeURL, az EF Core a blogpéldányokat is nyomon követi.

var blogs = await context.Blogs
    .OrderByDescending(blog => blog.Rating)
    .Select(
        blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog) })
    .ToListAsync();
public static string StandardizeUrl(Blog blog)
{
    var url = blog.Url.ToLower();

    if (!url.StartsWith("http://"))
    {
        url = string.Concat("http://", url);
    }

    return url;
}

Az EF Core nem követi nyomon az eredményben szereplő kulcs nélküli entitáspéldányokat. Az EF Core azonban a fenti szabályok szerint kulccsal követi nyomon az entitástípusok összes többi példányát.

Korábbi verziók

A 3.0-s verzió előtt az EF Core-nak volt néhány különbsége a nyomon követés módjában. Figyelemre méltó különbségek a következők:

  • Az Ügyfél és a Kiszolgáló kiértékelése oldalon leírtak szerint az EF Core a lekérdezés bármely részén támogatta az ügyfél kiértékelését a 3.0-s verzió előtt. Az ügyfélértékelés olyan entitások materializálását okozta, amelyek nem részei az eredménynek. Az EF Core tehát elemezte az eredményt, hogy észlelje a nyomon követendő elemet. Ennek a kialakításnak a következő eltérései voltak:

    • Ügyfélértékelés a vetítés során, amely materializálást okozott, de a materializált entitáspéldányt nem adta vissza, ezért nem volt nyomon követve. Az alábbi példa nem követte nyomon blog az entitásokat.

      var blogs = await context.Blogs
          .OrderByDescending(blog => blog.Rating)
          .Select(
              blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog) })
          .ToListAsync();
      
    • Az EF Core bizonyos esetekben nem követte nyomon a LINQ-összetételből érkező objektumokat. Az alábbi példa nem követte nyomon a(z) Post elemet.

      var blog = context.Blogs
          .Select(
              b =>
                  new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });
      
  • Amikor a lekérdezés eredményei kulcs nélküli entitástípusokat tartalmaztak, a teljes lekérdezés nem lett követve. Ez azt jelenti, hogy az eredményben szereplő kulcsokkal rendelkező entitástípusok sem lettek nyomon követve.

  • Az EF Core a nyomkövetés nélküli lekérdezésekben az identitásfeloldáshoz használható. Gyenge hivatkozásokat használt a már visszaadott entitások nyomon követéséhez. Ha tehát egy eredményhalmaz többször is ugyanazt az entitást tartalmazza, minden előforduláshoz ugyanazt a példányt kapja. Bár ha egy korábbi, azonos identitással rendelkező eredmény kiment a hatókörből, és meg lett tisztítva, az EF Core egy új példányt adott vissza.