COVID-19: Všechna školení nyní i on-line. Přečtěte si mé tipy na vzdělávání v době koronavirové.
Slovenská verzeSlovensky

Optimalizační testová otázka k Entity Framework

Zaujala mě jedna certifikační otázka (MCSD / 70-487), která docela dobře pracuje s různými aspekty použití Entity Frameworku. Otázka s rozepsaným řešením bez cenzury.

Miroslav Holec

Miroslav Holec

26. října. 2015
upraven 29. března. 2016

Tento článek je již velmi zastaralý. Zastaralé články nemusí popisovat aktuální stav technologií, nejideálnější řešení a můj aktuální pohled na danou technologii.

👨‍🎓 Nové školení EF Core pro rok 2020

Školení nejnovější verze Entity Framework Core přímo u Vás ve firmě. Naučíte se používat EF Core v celém životním cyklu aplikace od vytvoření modelu, změn v podobě migrací až po dotazování a profilování databázových dotazů.

Více o školení Entity Framework Core

Otázka

You are developing an ASP.NET MVC application. The application is an order processing system that uses the ADO.NET Entity Framework against a SQL Server database. It has a controller that loads a page that displays all orders along with customer information. Lazy loading has been disabled. The Order class is shown below.

public partial class Order
{
	public string CustomerId { get; set; }
	...
	public virtual Customer Customer { get; set; } 
}

You need to return the orders and customer information in a single round trip to the database. Which code segment should you use?

A

public ActionResult Index()
{
	IQueryable<Order> orders = db.Orders;
	orders = orders.Include("Customer");
	return View (orders.ToList());
}

B

public ActionResult Index()
{
	IQueryable<Order> orders = db.Orders.Include("Order.Customer")
	return View (orders.ToList());
}

C

public ActionResult Index()
{
	IQueryable<Order> orders = db.Orders;
	orders.Select(o => o.Customer).Load();
	return View (orders.ToList());
}

D

public ActionResult Index()
{
	IQueryable<Order> orders = db.Orders;
	return View (orders.ToList());
}

Na této otázce se mi líbí právě to, že každá možnost je na první pohled správná. Kód jde ve všech případech zkompilovat, nicméně výsledek se liší tím, jaká data se přenášejí z databáze.

Řešení

Důležité je dobře si přečíst zadání otázky. Jsou v něm požadavky a předpoklady, ze kterých správná odpověď jasně plyne. Důležité je hlavně následující:

  • Lazy loading has been disabled.
  • You need to return the orders and customer information in a single round trip to the database.

Protože je vypnutý Lazy Loading, můžeme rovnou vyloučit možnost D. Po odeslání dotazu se načtou pouze samotné objednávky bez zákazníka. Kdybychom chtěli později donačíst zákazník(a/y), neobešli bychom se bez dodatečných dotazů proti databázi.

Varianta C se jeví jako dobré řešení, protože třída Order má definovaného Customer jako virtual a tudíž můžeme skutečně použít explicitní loading. V hromadě ukázek na internetu je tato odpověď označená jako správná. Problém je, že v zadání je jasně řečeno: return data in a single round trip to the database. V případé této konstrukce se ale do databáze odesílá více dotazů v závilosti na použití Lazy Loadingu.

Zbývají možnosti A / B, které obě využívají Include() pro dotažení zákazníka. Obě varianty jsou syntakticky v pořádku ale varianta B odkazuje na "Order.Customer", což je chybné. Protože už nad objektem Order pracujeme, chceme použít jen Include("Customer").

Tím se dostáváme ke správné odpovědi A. Tady může na první pohled zmást konstrukce

IQueryable<Order> orders = db.Orders;

protože Db.Orders je typu DbSet<Order>. Přiřazení je ale v pořádku, viz.:

public class DbSet<TEntity> : DbQuery<TEntity>, IDbSet<TEntity>, 
    IQueryable<TEntity>, IEnumerable<TEntity>, IQueryable, IEnumerable
where TEntity : class
...

Odpálením dotazu dojde k načtení objednávek včetně zákazníků, čímž jsou splněny požadavky v otázce.

Při práci s EF lze jedné a té samé věci docílit mnoha různými způsoby. Sestavovat dotazy občas vyžaduje více zamyšlení nad tím, jaká data potřebuji, kdy je potřebuji a co s nimi chci dělat.


👨‍🎓 Webináře pro vývojáře - nyní zdarma

Vzdělávat se můžete i z pohodlí domova. Klasická školení jsem doplnil o související témata, která si můžete poslechnout v podobě živých webinářů. Přidejte se téměř 200 vývojářům, kteří se již připojili k mým webinářům!

Termín Místo
🍀 Software a nástroje, které používám 6. října 2020 online více
🍀 Co ještě nevíte o middlewares 9. října 2020 online více
🍀 Blazor Server 16. října 2020 online více
🍀 Novinky v .NET 5 pro REST API 21. října 2020 online více
Loading