06 | Integrating extra features and looking forward Christopher Harrison | Content Developer, Microsoft Adam Tuliper | Technical Evangelist, Microsoft
Module Overview Stored procedures Increasing user experience with concurrency detection A few best practices Looking forward with Entity Framework 7
Stored procedures
Store procedures Why use stored procedures? Limits dynamic sql Single point to secure – easier permissions Know exactly how DB is being queries Limits dynamic sql Still possible with sprocs, just more manual effort In general performance is _not_ a reason Virtually the same as sql query (pendulum swings both ways)
Stored procedures Support came as XX In the past could simply Database.SqlQuery Could map in the designer (which is going away) Code first will generate procedures context.Database.SqlQuery<myEntityType>( "mySpName @param1, @param2, @param3", new SqlParameter("param1", param1), new SqlParameter("param2", param2), new SqlParameter("param3", param3) );
Integrating stored procedures
Increasing user experience with concurrency detection
Concurrency As Chris showed, easy to implement via concurrency token [TimeStamp] modelBuilder.Entity<YourEntity>() .Property(e => e.Timestamp) .IsRowVersion(); Change detection can be enhanced via MVC Action Filters Let’s give the user the choice on how to proceed
Concurrency detection and user choice
A few best practices
Helpful hints in a web world Since the web layers (controller to view) are disconnected Always convert results to IEnumerable via .ToList() Ex. context.Albums.Where(o=>o.Title.Contains(search).ToList() Disable lazy loading in web environments context.Configuration.LazyLoadingEnabled = false; Use .Include to load related entities DbContext is not thread safe. Do not cache it! Always dispose DbContext when done
Context lifetime When context is gone, connection is gone Can’t (and shouldn’t) use connection from MVC view Get data, send to view Always execute result set when needed before exiting using() using (var context = new MusicContext()) { var albums = context.Albums .Where(o=>o.Title.Contains(search)) .ToList()); return View(albums); }
Watch out for… If you have two+ context classes One from selecting auth during app creation (Identity) One for your other entities Migrations should specify separate folders Enable-Migrations –MigrationsDirectory IdentityMigrations Enable-Migrations –MigrationsDirectory MusicStoreMigrations For complex joins, keep an eye on queries Doing lots of inserts? AutoDetectChangesEnabled = false;
Async when appropriate EF supports async queries Async allows current thread to be used elsewhere Useful in case of network, db delays (long operations) Although not all the time, caution of overloading db public async Task<ActionResult> Create(…) { if (ModelState.IsValid) db.Albums.Add(album); await db.SaveChangesAsync(); return RedirectToAction("Index"); } return View(album);
Consider Connection resiliency This is a connection retry policy Works great with async Four modes DefaultExecutionStrategy DefaultSqlExecutionStrategy DbExecutionStrategy SqlAzureExecutionStrategy throws RetryLimitExceededException
Connection Resiliency & Async
Looking forward with Entity Framework 7
Notable new features Designer has been removed Code first only Rewritten from ground up with performance in mind New platforms New data stores In memory database Update-Database now split Apply-Migration Script-Migration
EF 7 Quick Tour
Resources Additional patterns Reducing Code First Database Chatter http://www.asp.net/mvc/overview/older-versions/getting-started-with- ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work- patterns-in-an-asp-net-mvc-application Reducing Code First Database Chatter http://romiller.com/2014/06/10/reducing-code-first-database-chatter/ EF7 Project home https://github.com/aspnet/EntityFramework