Datenzugriff mit dem Entity Framework muss nicht langsam sein. In diesem Vortrag lernen Sie typische Stolperfallen kennen und wie Sie diese umschiffen können
11. „if you’re writing ADO.Net code by hand, you’re
stealing from your employer or client.”
Jeremy D. Miller, 7. November 2008,
http://codebetter.com/jeremymiller/2008/11/07/how-to-design-your-data-connectivity-strategy/
16. OR-Mapper
• Abstrahieren die Datenbank für uns
• Erlauben einen objektorientierten Zugriff auf die Datenbank
• Lassen uns unsere gewohnte Programmiersprache nutzen
• „Schützen(?)“ uns davor SQL schreiben zu müssen
• Sparen Entwicklungszeit
25. Messen Sie statt zu raten!
http://hibernatingrhinos.com/products/EFProf
26. Legen Sie eine ausreichende Menge an
realistischen Testdaten an
26http://www.red-gate.com/products/sql-development/sql-data-generator/
27. Laden Sie nicht mehr Daten als benötigt
using (var db = new NorthwindDb())
{
var products = db.Products;
foreach (var product in products)
{
Console.WriteLine("{0}",
product.ProductName);
}
}
SELECT [Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName],
[Extent1].[SupplierID] AS [SupplierID],
[Extent1].[CategoryID] AS [CategoryID],
[Extent1].[QuantityPerUnit] AS
[QuantityPerUnit],
[Extent1].[UnitPrice] AS [UnitPrice],
[Extent1].[UnitsInStock] AS [UnitsInStock],
[Extent1].[UnitsOnOrder] AS [UnitsOnOrder],
[Extent1].[ReorderLevel] AS [ReorderLevel],
[Extent1].[Discontinued] AS [Discontinued]
FROM [dbo].[Products] AS [Extent1]
28. Laden Sie nicht mehr Daten als benötigt
(Lösung)
var products = db.Products.Select(p
=> new {p.ProductName});
foreach (var product in products)
{
Console.WriteLine("{0}",
product.ProductName);
}
SELECT 1 AS [C1],
[Extent1].[ProductName] AS [ProductName]
FROM [dbo].[Products] AS [Extent1]
28
29. Laden Sie „Readonly Daten“ nicht in den
Change Tracker
var shippers = db.Shippers.ToList();
for (int i = 0; i < 200 && i <
shippers.Count; i++)
{
var shipper = shippers[i];
Console.WriteLine("{0} - {1}",
shipper.ShipperID,
shipper.CompanyName);
}
var shippers =
db.Shippers.AsNoTracking().ToList();
for (int i = 0; i < 200 && i <
shippers.Count; i++)
{
var shipper = shippers[i];
Console.WriteLine("{0} - {1}",
shipper.ShipperID,
shipper.CompanyName);
}
29
30. Laden Sie nur die Zeilen, die Sie wirklich
benötigen
var shippers = db.Shippers.ToList();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("{0} - {1}",
shippers[i].ShipperID,
shippers[i].CompanyName);
}
var shippers =
db.Shippers.Take(10).ToList();
foreach (var shipper in shippers)
{
Console.WriteLine("{0} - {1}",
shipper.ShipperID,
shipper.CompanyName);
}
30
31. Filtern Sie auf dem Server, nicht auf dem
Client
var customers = GetCustomers(db).Where(c =>
c.Country == "Germany");
foreach (var customer in customers)
{
Console.WriteLine("{0} - {1}",
customer.CustomerID, customer.CompanyName);
}
private IEnumerable<Customers>
GetCustomers(NorthwindDb db)
{
return db.Customers;
}
var customers = GetCustomersQry(db).Where(c
=> c.Country == "Germany");
foreach (var customer in customers)
{
Console.WriteLine("{0} - {1}",
customer.CustomerID, customer.CompanyName);
}
private IQueryable<Customers>
GetCustomersQry(NorthwindDb db)
{
return db.Customers;
}
31
32. Lassen Sie sich nicht durch die Intellisense in
falsche Richtungen leiten
var shippers =
db.Shippers.ToList().Take(10);
foreach (var shipper in shippers)
{
Console.WriteLine("{0} - {1}",
shipper.ShipperID,
shipper.CompanyName);
}
var shippers =
db.Shippers.Take(10).ToList();
foreach (var shipper in shippers)
{
Console.WriteLine("{0} - {1}",
shipper.ShipperID,
shipper.CompanyName);
}
32
33. Nutzen Sie Find Statt SingleOrDeafault um
Entitäten aus dem Cache zu laden
var s1 =
db.Shippers.SingleOrDefault(c =>
c.ShipperID == 1);
Console.WriteLine("S1: {0} - {1}",
s1.ShipperID, s1.CompanyName);
var s2 =
db.Shippers.SingleOrDefault(c =>
c.ShipperID == 1);
Console.WriteLine("S2: {0} - {1}",
s2.ShipperID, s2.CompanyName);
var shippers =
db.Shippers.Take(10).ToList();
foreach (var shipper in shippers)
{
Console.WriteLine("{0} - {1}",
shipper.ShipperID,
shipper.CompanyName);
}
33
34. Laden Sie nicht zum Löschen
var maxShipperId = db.Shippers.Max(s
=> s.ShipperID);
var shipper =
db.Shippers.Find(maxShipperId);
db.Shippers.Remove(shipper);
db.SaveChanges();
var maxShipperId = db.Shippers.Max(s
=> s.ShipperID);
// db.Shippers.Find(maxShipperId);
var shipper = new Shippers {ShipperID
= maxShipperId};
db.Shippers.Attach(shipper);
db.Shippers.Remove(shipper);
db.SaveChanges();
34
35. Behalten Sie Lazy Loading im Auge
var orders = db.Orders.ToList();
foreach (var order in orders)
{
Console.WriteLine("{0} {1}",
order.OrderID,
order.Customers.CompanyName);
}
var orders = db.Orders.Include(o=>
o.Customers).ToList();
foreach (var order in orders)
{
Console.WriteLine("{0} {1}",
order.OrderID,
order.Customers.CompanyName);
}
35
36. Annotieren Sie Ihr Model korrekt (Im Fall
von Code First)
• public string PreferedCommunication { get; set; }
wird zu nvarchar(max) in der Datenbank!
• [StringLength(50)]
public string PreferedCommunication { get; set; }
wird zu nvarchar(50) in der Datenbank
modelBuilder.Entity<Customers>()
.Property(e=> e.PreferedCommunication)
.IsUnicode(false);
varchar statt nvarchar
36
38. Sie haben ein Performance oder
Speicherproblem in Ihrer Anwendung?
Im Rahmen meiner Beratertätigkeit betreue ich seit vielen Jahren Kunden rum um die
Themen Datenzugriffsperformance, Anwendungsperformance und Memory Leak
Analysen.
Kommen Sie bei Bedarf gerne auf mich zu:
andre@andrekraemer.de | http://andrekraemer.de
38
39. Meine Dienstleistungen
• Schulungen
• ASP.NET / JavaScript / AngularJS
• Xamarin
• Cordova
• TX Text Control
• Infragistics NetAdvantage
• Team Foundation Server
• .NET Datenzugriff (Entity Framework, NHibernate, Micro O/R Mapper)
• Consulting
• Durchführung von Technologieworkshops
• Code- / Architekturreviews
• Analyse von managed Memory Leaks
• Prototypenentwicklung
• Remote Entwickler-Support
• Projektbegleitendes Coaching
• Softwareentwicklung
• Mobile Apps (Android, iOS, Windows 10, Windows 8, Windows Phone)
• Entwicklung von Web-Anwendungen mit ASP.NET und AngularJS
• Entwicklung von Desktop Anwendungen
39andre@andrekraemer.de | http://andrekraemer.de | http://andrekraemer.de/blog | http://github.com/AndreKraemer
Hinweis der Redaktion
Das bedeutet, dass wir in 30 % unserer Arbeitszeit keinen Mehrwert in der Form von Benutzer-Features für unser eigentliches Produkt welches wir entwickeln schaffen können, sondern damit beschäftigt sind Infrastrukturcode zu schreiben.
Natürlich ist dies keine wirklich gute Idee, denn Datenzugriff - oder Persistenz - ist ein gelöstes Problem. ..