Entity Framework is now well established as Microsoft’s de-facto data access story. It has notched up 5 impressive revisions already and version 6 started of with a bang in terms of development story. Microsoft open sourced Entity Framework (version 6 onwards), the development code was available on CodePlex, they started accepting pull requests from the community and everyone had access to a nightly build as well as meeting and design notes. While this is a laudable effort given the flak MS has drawn in the past, the reassuring part about the new Development Model was that, releases were still controlled by Microsoft (much like the ASP.NET MVC framework) and the same Support Agreements as of version 5 held true for Enterprise customers who may have had concerns with the new Model.
But today, we are not going to discuss the pros and cons of EF going OSS. Let’s get started and see what new customizations we can do on top of Code First conventions.
Customizing Custom Code First Conventions
This implies that we now have greater flexibility in modeling our Databases. Earlier, EF Code first, followed certain naming conventions and derived DB Names/Column Names etc. from its pre-set conventions. For example the Primary Key was expected to be EntityName+’Id’ or just ‘Id’. We could always override them by putting the override via attributes wherever we wanted. But if we wanted to do bulk overrides, we had no option but copy paste. Boring!
Let’s look at an example. Lets say we have a Model class called Post for storing Blog Posts in an ASP.NET MVC Application. Mind you we are using Visual Studio 2013 Preview so it uses the EF Beta by default. If you are using older version of VS, make sure you are using .NET Framework 4.5 and download the latest package from Nuget using
install-package EntityFramework -pre
The –pre tells Nuget to look for pre-release versions and get the latest one around.
Our Post entity has the following structure
public class Post
{
public int PkPostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
Now as we can see, it has a weird Key with a Pk prefix. Well that’s what our DBA will permit so that’s what it’s gonna be. Imagine this across a more elaborate schema and adding the [Key] attribute for it is not a very enticing proposition.
Thanks to the new capabilities in Entity Framework 6, we can now ‘tell’ EF that all properties starting with Pk are going to be Primary Key columns.
To do this, we have to override the OnModelCreating method in our DbContext. But we haven’t created one yet!
Since we started off with an ASP.NET MVC application, we can usually build the application and then scaffold a new PostsController that uses EntityFramework. This will generate the DB Context, which in case of this example is called EF6WhatsNewContext.
But in our case, as soon as we hit Add, we’ll get the following! Oops, if you are not following EF specified default conventions, no cookies for you from the scaffolder.
So we’ll reset the PK to PostId and Scaffold the Controller. Then change the ID back to PkPostId. Don’t forget to update the scaffolded views to use PkPostId in the Html Helpers as well, else you’ll get errors at runtime.
Customizing Naming Conventions for Primary Keys
We setup our Custom EF6WhatsNewContext as follows:
public class EF6WhatsNewContext : System.Data.Entity.DbContext
{
public EF6WhatsNewContext() : base("name=EF6WhatsNewContext")
{
}
public DbSet<EF6WhatsNew.Models.Post> Posts { get; set; }
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder
modelBuilder)
{
modelBuilder.Properties().Where(p => p.Name.StartsWith("Pk"))
.Configure(p => p.IsKey());
}
}
Apart from the standard constructor and the DbSet property for Post, we have overridden the OnModelCreating method. Here from the modelBuilder, we’ve pulled out all the Properties() in the model. This Properties() API is new.
On this list of properties, we’ve applied a Where clause that gives us the reflected details of the Property/Column name. We picked the Name property and checked to see if it starts with Pk.
Once we have all the properties, we use the Configure method and define the property is the key by calling the IsKey() function.
If we build the application now and try to scaffold, it will succeed. If we run the application now and navigate to the /Posts page, we’ll see an empty Index page.
Add a row of data and then use SQL Server Explorer to explore the DB Structure
As we can see here, the PkPostId is now setup as Primary Key.
Customizing Column Sizes
From the above diagram however, we see that the Title and Content are both set to nvarchar(max). We know our DBA is going to throw a hissy fit if they see this. We can devise a convention that says anywhere in the Schema if we have properties like Name, Title, Email the length should be limited to nvarchar(200). Content can be nvarchar(max).
Back in the OnModelCreating method of our DbContext, we add the following Property definition
modelBuilder.Properties<string>()
.Where(p => p.Name.Contains("Title") ||
p.Name.Contains("Name") ||
p.Name.Contains("Email")
).Configure(p => p.HasMaxLength(200));
This states that any column name of type string containing the words Title, Name or Email will have a max length of 200.
Now our database is already created so we have to use EF Migrations to setup the changes. In the Package Manager Console, we enter the following to enable the migrations first up
PM> enable-migrations
This will setup the initial state of the DB. Next we’ll ask EF to scaffold out the changes with respect to the new Property rule we added.
PM> add-migration TitleMaxLength
We’ll see EF generates a TitleMaxLength class in the Migrations folder where it has commands to Alter the column’s max length
public partial class TitleMaxLength : DbMigration
{
public override void Up()
{
AlterColumn("dbo.Posts", "Title", c => c.String(maxLength: 200));
}
public override void Down()
{
AlterColumn("dbo.Posts", "Title", c => c.String());
}
}
To update our DB with this change, we apply the Migration as follows
PM> update-database
Now if we go back to the DB in the Explorer, we’ll see the Max length has been set appropriately.
Re-configuring Column Names
Imagine Halfway down our project, our DB experts do a DB review and reject the column naming convention altogether. They want column names to be prepended with the table name, all UPPER case and each Word in the name should be separated by underscore. So Post.PkPostId should be POST_PK_POST_ID (Okay, okay that’s a weird and unlikely requirement, just play along to see how we get to it).
Actually we have a solution for this too. Back in the DbContext class we add the following method:
private string GetColumnName(System.Reflection.PropertyInfo propertyInfo)
{
var result = System.Text.RegularExpressions.Regex.Replace(
propertyInfo.Name,
".[A-Z]", m => m.Value[0] + "_" + m.Value[1]);
return result.ToUpper();
}
This method takes in a propertyInfo, uses it’s name to generate a string that separates out the Pascal case (or dot separated) words and joins them with underscore. Finally it converts the whole thing to upper case and returns it.
This method does what we want now let’s apply it. We add the following to the OnModelCreating method
modelBuilder.Properties()
.Configure(p => p.HasColumnName(GetColumnName(p.ClrPropertyInfo)));
This basically updates all column names using the return value of the GetColumnName method. We build the application and scaffold the next Migration. Once we apply the DB changes and peek at the DB, it looks as follows:
Pretty neat! That introduces the Code First Convention features in the upcoming Entity Framework 6. There are tons of more features that we’ll cover as we get closer to final release and beyond.
Conclusion
With the Code First convention enhancements, configuring conventions has become much easier using the Fluent API. This will reduce a lot of repetitive work and a ton of attribute clutter if your DB conventions don’t matchup with EF defaults.
Download the entire source code of this article (Github)
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn