{"id":6755,"date":"2016-09-29T13:39:01","date_gmt":"2016-09-29T20:39:01","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/dotnet\/?p=6755"},"modified":"2021-09-30T11:50:41","modified_gmt":"2021-09-30T18:50:41","slug":"implementing-seeding-custom-conventions-and-interceptors-in-ef-core-1-0","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/implementing-seeding-custom-conventions-and-interceptors-in-ef-core-1-0\/","title":{"rendered":"Implementing Seeding, Custom Conventions and Interceptors in EF Core 1.0"},"content":{"rendered":"<p>This post was written by <strong>Alina Popa<\/strong>, a software engineer on the .NET team.<\/p>\n<p><em><strong>Updated 10\/5\/2016:<\/strong> This post has been updated to use improved Entity Framework Core techniques which don\u2019t rely on internal APIs.<\/em><\/p>\n<h2>Implementing Seeding, Custom Conventions and Interceptors in EF Core 1.0<\/h2>\n<h2>Introduction<\/h2>\n<p>Entity Framework Core (EF Core) is a lightweight and extensible version of the Entity Framework (EF) data access technology which is cross-platform and supports multiple database providers. You can find a comparison of EF Core vs. EF6 under the <a href=\"https:\/\/docs.efproject.net\/en\/latest\/efcore-vs-ef6\/index.html\">Entity Framework documentation<\/a>.<\/p>\n<p>When moving an application from EF6 to EF Core, you may encounter features that existed in EF6 but either are not present or are not yet implemented in EF Core. For many of those features, however, you can implement equivalent functionality.<\/p>\n<h2>Seeding<\/h2>\n<p>With EF6 you can seed a database with initial data by overriding one of the following <code>Seed()<\/code> methods:<\/p>\n<ul>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/hh829453(v=vs.113).aspx\"><code>DbMigrationsConfiguration&lt;TContext&gt;.Seed()<\/code><\/a><\/li>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/gg679410(v=vs.113).aspx\"><code>DropCreateDatabaseIfModelChanges&lt;TContext&gt;.Seed()<\/code><\/a><\/li>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/gg679506(v=vs.113).aspx\"><code>DropCreateDatabaseAlways&lt;TContext&gt;.Seed()<\/code><\/a><\/li>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/gg679221(v=vs.113).aspx\"><code>CreateDatabaseIfNotExists&lt;TContext&gt;.Seed()<\/code><\/a><\/li>\n<\/ul>\n<p>EF Core does not provide similar APIs, and database initializers also no longer exist in EF Core. To seed the database, you would put the database initialization code in the application startup. If you are using migrations, call <code>context.Database.Migrate()<\/code>, otherwise use <code>context.Database.EnsureCreated()\/EnsureDeleted()<\/code>.<\/p>\n<p>The patterns for seeding the database are discussed in issue <a href=\"https:\/\/github.com\/aspnet\/EntityFramework\/issues\/3070\">3070<\/a> in the Entity Framework Core repository on GitHub. The recommended approach is to run the seeding code within a service scope in <code>Startup.Configure()<\/code>:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/alinapopa\/533008b3057ef1a5a3f244b4cf34fab2.js\"><\/script><\/p>\n<p>You can find <a href=\"https:\/\/github.com\/rowanmiller\/UnicornStore\/blob\/master\/UnicornStore\/src\/UnicornStore\/Startup.cs#L66\">here<\/a> an example of database initialization that uses migrations, along with an implementation example of <a href=\"https:\/\/github.com\/rowanmiller\/UnicornStore\/blob\/master\/UnicornStore\/src\/UnicornStore\/Models\/UnicornStore\/UnicornStoreExtensions.cs\">EnsureSeedData()<\/a> method. The <a href=\"https:\/\/github.com\/aspnet\/MusicStore\">MusicStore<\/a> sample also uses this pattern for seeding.<\/p>\n<p>Please note that, in general, it is recommended to apply these operations manually (rather than performing migrations and seeding automatically on startup), to avoid racing conditions when there are multiple servers, and unintentional changes.<\/p>\n<h2>Custom Conventions<\/h2>\n<p>In Entity Framework 6 we can create custom configurations of properties and tables by using model-based conventions. For example, the following code in EF6 creates a convention to throw an exception when the column name is longer than 30 characters:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/mjrousos\/60682be4c14f05c9e3094a97a2143be4.js?file=2-EF6-Conventions.cs\"><\/script><\/p>\n<p>EF Core does not provide the <code>IStoreModelConvention<\/code> interface; however, we can create this convention by accessing the data model inside the OnModelCreating() method:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/alinapopa\/e83a5aacf6d8db5bb10b09169dc036ac.js\"><\/script><\/p>\n<p>Note that the model is not read-only and it can be modified inside the loop.<\/p>\n<h2>Interceptors<\/h2>\n<p>Among other useful things, Entity Framework 6 provides the ability to intercept a context using <code>IDbCommandInterceptor<\/code>. Interceptors let you to get into the pipeline just before and just after a query or command is sent to the database.<\/p>\n<p>Entity Framework Core doesn\u2019t have any interceptors yet, but an important subset of the functionality of the interceptors can be achieved by using simple patterns, such as overriding <code>DbContext.SaveChanges<\/code>:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/alinapopa\/f1377f5ee5894e2113f75026411c4a14.js\"><\/script><\/p>\n<p>Some notes on the example above:<\/p>\n<ul>\n<li>The call to <code>ChangeTracker.DetectChanges()<\/code> is to ensure that the change tracker is aware of the changes made to the entities, e.g. if you set .Category to a new Category on an existing Product, the new Category wouldn\u2019t be tracked until <code>DetectChanges()<\/code> is called or it\u2019s added explicitly through DbSet or ChangeTracker.<\/li>\n<li>Setting <code>AutoDetectChangesEnabled<\/code> to false before calling the base <code>SaveChanges<\/code> is for performance reasons, to avoid calling <code>DetectChanges()<\/code> again.<\/li>\n<\/ul>\n<p>Interceptors and seeding are high on the feature backlog and the Entity Framework team plans to address them in the near future.<\/p>\n<h2>Useful Links<\/h2>\n<ul>\n<li><a href=\"https:\/\/docs.efproject.net\/en\/latest\/efcore-vs-ef6\/porting\/index.html\">Moving an application from EF6 to EF Core<\/a><\/li>\n<li>EF Core <a href=\"https:\/\/github.com\/aspnet\/EntityFramework\/issues\/629\">Migrations: Seed Data<\/a> GitHub issue<\/li>\n<li><a href=\"https:\/\/github.com\/aspnet\/EntityFramework\/issues\/626\">Lifecycle Hooks<\/a> GitHub issue<\/li>\n<li><a href=\"https:\/\/github.com\/aspnet\/EntityFramework\/wiki\/Roadmap\">EF Core Roadmap<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This post was written by Alina Popa, a software engineer on the .NET team. Updated 10\/5\/2016: This post has been updated to use improved Entity Framework Core techniques which don\u2019t rely on internal APIs. Implementing Seeding, Custom Conventions and Interceptors in EF Core 1.0 Introduction Entity Framework Core (EF Core) is a lightweight and extensible [&hellip;]<\/p>\n","protected":false},"author":7413,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[4,9,70],"class_list":["post-6755","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","tag-net","tag-net-core","tag-entity-framework"],"acf":[],"blog_post_summary":"<p>This post was written by Alina Popa, a software engineer on the .NET team. Updated 10\/5\/2016: This post has been updated to use improved Entity Framework Core techniques which don\u2019t rely on internal APIs. Implementing Seeding, Custom Conventions and Interceptors in EF Core 1.0 Introduction Entity Framework Core (EF Core) is a lightweight and extensible [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/6755","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/7413"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=6755"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/6755\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=6755"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=6755"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=6755"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}