Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
Az Entity Framework Core általános szabályként a lehető legtöbb lekérdezést próbálja kiértékelni a kiszolgálón. Az EF Core a lekérdezés egyes részeit paraméterekké alakítja, amelyeket az ügyféloldalon értékelhet ki. A lekérdezés többi részét (a generált paraméterekkel együtt) az adatbázis-szolgáltató adja meg, hogy meghatározza a kiszolgálón kiértékelendő egyenértékű adatbázis-lekérdezést. Az EF Core támogatja az ügyfélrészleges értékelést a legfelső szintű projektálásban (lényegében az utolsó hívásra Select()). Ha a lekérdezés legfelső szintű vetülete nem fordítható le a kiszolgálóra, az EF Core lekéri a szükséges adatokat a kiszolgálóról, és kiértékeli a lekérdezés fennmaradó részeit az ügyfélen. Ha az EF Core a legfelső szintű kivetítésen kívül bármely olyan kifejezést észlel, amely nem fordítható le a kiszolgálóra, akkor futásidejű kivételt okoz. Tekintse meg , hogyan működnek a lekérdezések annak megértéséhez, hogy az EF Core hogyan határozza meg, hogy mit nem lehet lefordítani a kiszolgálóra.
Megjegyzés:
A 3.0-s verzió előtt az Entity Framework Core a lekérdezés bármely pontján támogatta az ügyfél kiértékelését. További információkért tekintse meg az előző verziók szakaszt.
Jótanács
A cikk mintáját a GitHubon tekintheti meg.
Ügyfélértékelés a legfelső szintű előrejelzésben
Az alábbi példában egy segédmetódussal szabványosítjuk a blogok URL-címeit, amelyeket egy SQL Server-adatbázisból adnak vissza. Mivel az SQL Server-szolgáltatónak nincs rálátása a metódus implementálására, nem fordítható le SQL-be. A lekérdezés minden más aspektusát kiértékeli az adatbázis, de a visszaadott URL adatok átadása ezen a módszerrel történik az ügyfélen.
var blogs = await context.Blogs
.OrderByDescending(blog => blog.Rating)
.Select(
blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog.Url) })
.ToListAsync();
public static string StandardizeUrl(string url)
{
url = url.ToLower();
if (!url.StartsWith("http://"))
{
url = string.Concat("http://", url);
}
return url;
}
Nem támogatott ügyfélértékelés
Bár az ügyfélértékelés hasznos, néha gyenge teljesítményt eredményezhet. Fontolja meg a következő lekérdezést, amelyben a segédmetódust most egy where szűrőben használják. Mivel a szűrő nem alkalmazható az adatbázisban, a szűrő alkalmazásához az összes adatot memóriába kell húzni. A szűrő és a kiszolgálón lévő adatok mennyisége alapján az ügyfélértékelés gyenge teljesítményt eredményezhet. Az Entity Framework Core tehát blokkolja az ilyen ügyfélértékelést, és futásidejű kivételt vet ki.
var blogs = await context.Blogs
.Where(blog => StandardizeUrl(blog.Url).Contains("dotnet"))
.ToListAsync();
Explicit ügyfélértékelés
Előfordulhat, hogy bizonyos esetekben explicit módon kell kikényszerítenie az ügyfélértékelést, például:
- Az adatok mennyisége kicsi, így az ügyfél kiértékelése nem jár hatalmas teljesítménybírsággal.
- A használt LINQ-operátor nem rendelkezik kiszolgálóoldali fordítással.
Ilyen esetekben explicit módon választhatja az ügyfélértékelést olyan metódusok meghívásával, mint az AsEnumerable vagy ToList (AsAsyncEnumerable vagy ToListAsync az aszinkron). A AsEnumerable használatával streamelné az eredményeket, míg a ToList használata pufferelést okozna egy lista létrehozásával, amely további memóriát igényel. Ha azonban többször is számba szeretné adni az eredményeket, akkor az eredmények listában való tárolása jobban segít, mivel csak egy lekérdezés van az adatbázishoz. Az adott használattól függően érdemes kiértékelni, hogy melyik módszer hasznosabb az esethez.
var blogs = context.Blogs
.AsAsyncEnumerable()
.Where(blog => StandardizeUrl(blog.Url).Contains("dotnet"))
.ToListAsync();
Jótanács
Ha AsAsyncEnumerable használja és szeretné tovább komponálni a lekérdezést ügyféloldalon, akkor használhatja a System.Interactive.Async könyvtárat, amely operátorokat határoz meg az aszinkron enumerációkhoz. További információ: ügyféloldali linq operátorok.
Lehetséges memóriavesztés az ügyfélértékelésben
Mivel a lekérdezés fordítása és összeállítása költséges, az EF Core gyorsítótárazza az összeállított lekérdezési tervet. A gyorsítótárazott delegált ügyfélkódot használhat a felső szintű kivetítés ügyfél általi értékelése során. Az EF Core paramétereket hoz létre a fa ügyfél által kiértékelt részeihez, és a paraméterértékek lecserélésével újra felhasználja a lekérdezési tervet. A kifejezésfa bizonyos állandói azonban nem konvertálhatók paraméterekké. Ha a gyorsítótárazott delegált ilyen állandókat tartalmaz, akkor ezek az objektumok nem gyűjthetők szemétként, mivel továbbra is hivatkoznak rájuk. Ha egy ilyen objektum dbContextet vagy más szolgáltatásokat tartalmaz, az idővel az alkalmazás memóriahasználatának növekedéséhez vezethet. Ez a viselkedés általában memóriavesztés jele. Az EF Core kivételt alkalmaz, ha olyan típusú állandókra kerül sor, amelyek nem képezhetők le az aktuális adatbázis-szolgáltató használatával. A gyakori okok és azok megoldásai a következők:
- Példánymetódus használata: Ha példánymetódusokat használ egy ügyfélvetítésben, a kifejezésfa a példány állandóját tartalmazza. Ha a metódus nem használ adatokat a példányból, fontolja meg a módszer statikussá tételét. Ha példányadatokra van szüksége a metódus törzsében, adja át az adott adatokat argumentumként a metódusnak.
-
Állandó argumentumok átadása a metódusnak: Ez az eset általában akkor fordul elő, amikor a
thisszolgáltatás egy ügyfélmetódusban van használva. Fontolja meg az argumentum felosztását több skaláris argumentumra, amelyeket az adatbázis-szolgáltató leképezhet. - Egyéb állandók: Ha minden más esetben konstanssal találkozunk, akkor kiértékelheti, hogy szükség van-e az állandóra a feldolgozás során. Ha szükség van az állandóra, vagy ha a fenti esetekből nem tud megoldást használni, hozzon létre egy helyi változót az érték tárolásához, és használja a helyi változót a lekérdezésben. Az EF Core paraméterként fogja átalakítani a helyi változót.
Korábbi verziók
A következő szakasz a 3.0 előtti EF Core-verziókra vonatkozik.
A régebbi EF Core-verziók támogatták az ügyfél kiértékelését a lekérdezés bármely részén – nem csak a legfelső szintű előrejelzésben. Ezért működtek megfelelően a nem támogatott ügyfélértékelési szakaszban közzétetthez hasonló lekérdezések. Mivel ez a viselkedés észrevétlen teljesítményproblémákat okozhat, az EF Core egy ügyfélértékelési figyelmeztetést naplózott. A naplózási kimenet megtekintéséről további információt a Naplózás című témakörben talál.
Opcionálisan az EF Core lehetővé tette, hogy módosítsa az alapértelmezett viselkedést úgy, hogy kivételt tegyen, vagy semmit se tegyen az ügyfélértékelés során (kivéve a kivetítésben). A kivételdobás viselkedése hasonlóvá teszi a 3.0-s viselkedéshez. A viselkedés módosításához konfigurálnia kell a figyelmeztetéseket, miközben beállítja a környezet opcióit – jellemzően DbContext.OnConfiguring, vagy ha ASP.NET Core-t használ, akkor Startup.cs alatt.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;")
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}