Im sechsten Teil meiner Entity Framework Webcast Serie zeige ich, wie die IUnitOfWork erweitert werden muss, um SQL Abfragen und Befehle auszuführen. Im Fokus stehen Value Functions und Stored Procedures.
Dafür stellt das Entity Framework 2 Schnittstellen bereit:
- SqlQuery
- ExecuteSqlCommand
Ein wichtiger Hinweis an dieser Stelle, welcher eingehender in meinem Webcast erwähnt wird: Zum Ausführen einer SQL Query existieren 2 Implementierungen:
- DbContext.Database.SqlQuery<TElement>(string sql, params Object[] parameters)
- DbSet.SqlQuery(string sql, params Object[] parameters)
Der wesentliche Unterschied besteht darin, dass im ersten Fall die zurückgegebenen Entitäten nicht getrackt werden, im zweiten hingegen schon. Das ist leicht nachvollziehbar, so muss bei DbContext.Database.SqlQuery ein generischer Parameter, der den Rückgabewert darstellt, übergeben werden. Im Falle von DbSet.SqlQuery ist dies nicht nötig, schließlich befindet man sich zum Zeitpunkt der Abfrage auf einem konkreten Set an Entitäten, die über den Context aufgelöst wurden.
Meine vorgestellte Lösung geht den gleichen Weg wie die in Teil 3 beschriebenen Queries, d.h. es werden quasi SQL Query und Command Repositories angelegt, um einer Streuung innerhalb der Anwendungslandschaft entgegenzuwirken.
Schließlich noch zwei Sicherheitshinweise:
- Die SQL Befehle werden mit den Berechtigungen des Contexts bzw. des darunterliegenden Sicherheitstoken ausgeführt
- Beim Erstellen des SQL Strings sollte aus Sicherheitsgründen gegenüber Injections mit String.Format() oder alternativ mit SqlParameters gearbeitet werden.
I wrote this blog post as an answer of a question from the Netherlands, so I want to complete this article with a quote:
“When you execute a SqlQuery from Database, the results are never tracked by the context, even if the query returns types that are in the model an known by the context. If you do not want the results to be changed-tracked, use DbContext.Databae.SqlQuery.
Results of a DbSet.SqlQuery will be tracked by the context. Ensuring that results are change-tracked is the primary reason you would choose to use DbSet.SqlQuery over Database.SqlQuery.” (Programming Entity Framework, Page 226)
Weitere Quellen:
- Using DbContext in EF – Part 10 – Raw SQL Queries
- Programming Entity Framework: DbContext
- Alle Teiler meiner Webcastserie
- Mein YouTube Channel
- Alle meine Blogeinträge zum Entity Framework
- Den Code auf Github
Mit Tag(s) versehen: EntityFramework, T-SQL
[…] Teil 6 – Stored Procedures und SQL Queries: In Anlehnung an Teil 3 baue ich hier ein entsprechendes Repository für reine SQL Abfragen und Stored Procedures auf. […]
LikeLike
Thumbs up, Great Work, and Amazing, again eagerly waiting on next video on Stored Procedure,,
Regards,
-SAM
LikeLike
next video is online and it’s about unit testing. the code is also available on my github site.
LikeLike
Deine Webcasts sind gefährlich, weil es die Leute glauben macht, dass sie ihre Lösungen analog aufsetzten müssen.
Beispiel: Der DbContext ist eine UnitOfWork. Es gibt keinen erkennbaren Grund für eine weitere UnitOfWork. Im Gegenteil: die Tatsache, dass Du den Begriff separat zu dem DbContext einführst, verschleiert den eigentlichen Zusammenhang.
LikeLike
Hey Carsten,
in keinem meiner Webcasts sage ich, dass der eigene Code analog implementiert werden muss. Viel eher weise ich in fast jedem Webcast darauf hin (so auch in meinem ganz neuen Nummer 7), dass es eine Möglichkeit zur Implementierung ist. Ich weise ebenfalls immer wieder auf Alternativen hin. Teilweise sind auch Beispiele enthalten, wie wir es intern gar nicht nutzen, ich es aber für diverse Leser eingebaut habe.
Zu deinem Beispiel: Ich hatte dies bereits in dem Webcast (ggf. auch im Blog?bin mir aber nicht mehr sicher) über die UnitOfWork erläutert. Es gibt drei wesentliche Gründe, die dies notwendig machen bzw. machen können: DbContext bedeutet, dass man eine direkte Referenz auf das Entity Framework benötigt, wodurch der Austausch der Persistenzschicht sehr erschwert wird. Darüber hinaus hat es Microsoft versäumt dafür ein Interface zur Verfügung zu stellen, sodass auch die Testbarkeit leidet. Und als Punkt 3 ist die Intension zur einem Query Repository zu nennen, sodass Queries nicht mehr überall in der Anwendung verstreut sind bzw. redundant geschrieben werden.
LikeLike