Customizing the EF Entity Templates

The nice thing about Entity Framework is that anytime you are using one of the entity template generation capabilities, they are pretty easily customizable. This, of course, means that you are NOT using the pure code-first API most likely (however, to an existing database defines a T4 template). In this blog post, we’re going to quickly update the T4 template to change the default rendering:

using System;
using System.Collections.Generic;
    
public partial class State_LKP
{
    public int StateID { get; set; }
    public string StateCode { get; set; }
    public string StateName { get; set; }
}

To add additional information that the application can later use for metadata purposes, such as the following:

using System;
using System.Collections.Generic;
    
public partial class State_LKP
{
    public const string StateID_Name = "StateID";
    public int StateID { get; set; }
    
    public const int StateCode_MAX_LENGTH = 10;		
    public const string StateCode_Name = "StateCode";
    public string StateCode { get; set; }
    
    public const int StateName_MAX_LENGTH = 50;
    public const string StateName_Name = "StateName";
    public string StateName { get; set; }
}

Notice that each column has a constant defining the name, as well as a constant defining it’s max length defined in the database (if a string).

To do this, we need to open up the .tt file that generates each of the entities. In my version, around line 66, we have the following snippet.

var simpleProperties = typeMapper.GetSimpleProperties(entity);
if (simpleProperties.Any())
{
    foreach (var edmProperty in simpleProperties)
    {
#>
    <#=codeStringGenerator.Property(edmProperty)#>
<#
    }
}

Notice that this snippet loops through each of the simple properties (the properties defined one for each column) and renders out a definition (note codeStringGenerator is a class defined in the T4 template that defines all of the markup. I didn’t choose to modify that here). To add the name constants and the max length constants, the updated samples were changed to the following code sample. Comments below indicate the changes made.

var simpleProperties = typeMapper.GetSimpleProperties(entity);
if (simpleProperties.Any())
{
    //edmProperty of type EdmProperty
    foreach (var edmProperty in simpleProperties)
    {
        //Check max length - if any max length, then write out a constant
	 if(edmProperty.MaxLength.HasValue)
                {
                        #>
 
                        public const int <#= edmProperty.Name #>_MAX_LENGTH = 
                            <#= edmProperty.MaxLength.Value #>;
 
                        <#
                }	


         public const string <#= edmProperty.Name #>_Name = 
               "<#= edmProperty.Name #>";

    <#=codeStringGenerator.Property(edmProperty)#>
    <#
    }
}

Here we add constants to the output of the properties and everything generates great. You may say it would be better to use attributes; that is possible as well, but for that I’d recommend editing the CodeStringGenerator class (in the T4 template) and update the Property method directly instead.

The T4 template is available here: http://pastebin.com/42NiuwDE

Entity Framework 6 Update Taking REALLY Long Time

I had a strange issue updating the Entity Framework model against a newly built SQL Server 2014 database.  For some reason, it was talking a REALLY long time, even hours to connect.  Using SQL Server Profiler, we saw some activity which never completed.  I couldn’t figure it out until someone helped me by sending me this link: https://entityframework.codeplex.com/workitem/2445

Other users had indicated that Cumulative Update 5 needed to be installed and so this contained the resolution to the issue.  If you don’t want to install Cumulative Updates, changing the compatibility level to SQL Server 2012 worked just fine as well.  Changing the compatibility level immediately takes effect without server level restarts.

Entity Framework Table Tricks

I’ve seen out on the web quite a few questions about how to do this or that with Entity Framework, so I’d thought I’d write up a solution to various ways to work with tables and to customize entities.

Sets

Suppose we have a context with a Customers table; by default, the Entity Framework code generator generates code that allows the consumer to do the following.

var ctx = new EFContext();
ctx.Customers.Where(i => ..);

The Customers property is a DBSet object that is responsible for “table management”, which is not quite right but a good quick way to understand it. The DBSet is the primary mechanism for generating queries against the table and adding new objects to the table. Entity Framework code generators create wrappers around this object, but also expose the following methods in two forms:

public System.Data.Entity.DbSet Set(Type type);
public System.Data.Entity.DbSet Set();

Referring to a table generically using the set method comes in handy when you want to simplify your data access code. To explain what I mean, let’s look at a small sample. We may want to use the repository pattern like this:

public interface IRepository
 where T: class
{

    IEnumerable GetAll();

}

public class CustomerRepository : IRepository
{
   public IEnumerable GetAll()
   {
      var ctx = new EFContext();
      return ctx.Customers.ToList();
   }
}

Note how we write the code in each and every repository; we have 1 now, but as the system grows, each repository has to write this same code over and over again. Sure, we can generate it automatically, but we can also do this:

public abstract class BaseRepository : IRepository
{
   public IEnumerable GetAll()
   {
      var ctx = new EFContext();
      return ctx.Set().ToList();
   }
}

public class CustomerRepository : BaseRepository
{

}

Notice the set method usage and how this one common method prevents us from having to write common code. Now we have one method shared across all repositories. We could also use the other override like so:

ctx.Set(typeof(Customer));

Although, it’s far less flexible than the generic form. A lot of the common options are not available out-of-the-box. One important use you can use it to add objects to the database, however.

var customer = new Customer { .. };
ctx.Set(typeof(Customer)).Add(customer);
ctx.Set().Add(customer);

ctx.SaveChanges();

SaveChanges then commits any changed made, raising errors for any validations or update exceptions.

Using Interfaces

Using interfaces can add in some nice flexibility. Suppose we have an interface like this:

public interface IAuditEntity
{
   public DateTime Entered { get; set; }

   public DateTime? Updated { get; set; }
}

Supposing that all of your entities implement this interface, you can simplify your repositories by creating common code:

public abstract class BaseRepository
{

   public IEnumerable GetUpdatedSince(DateTime check)
      where T: IAuditEntity
   {
      var ctx = new EFContext();
      return ctx.Set().Where(i => i.Updated != null && i.Updated.Value > check);
   }

}

While the example above is not the most useful, it illustrates what can be done to create common routines in entity framework. Since Updated matches the name of a field in the table being queried, Entity Framework resolves this correctly; if the name doesn’t match, an exception will be raised saying the property defined in the expression doesn’t exist in the table.

Functions

What floored me though is through a method, Entity Framework can bridge the gap and provide common code. For instance, suppose we had entities like this:

public class Customer
{
   public string Country { get; set; }
}

public class Employee
{
  public string PrimaryCountry { get; set; }
}

We couldn’t create an interface with the name Country, because Employee doesn’t have a matching property. We could change the name, but for the sake of the example, let’s keep them different. Since property name mismatches cause errors, we can surprisingly use functions. An architect had shown me this and I was floored, simply because properties don’t work. But by doing:

public interface ICountry
{
   public string CountryExpression();
}

public class Customer : ICountry
{
   public string Country { get; set; }

   public string CountryExpression()
   {
      return this.Country;
   }
}

public class Employee
{
  public string PrimaryCountry { get; set; }


   public string CountryExpression()
   {
      return this.PrimaryCountry;
   }
}

And then doing the following in the query will work:

public IEnumerable GetByCountry(string country)
 where T: ICountry
{
  var ctx = new EFContext();
  return ctx.Set().Where(i => i.CountryExpression() == country);
}

An architect showed me this trick, and I was floored that it worked since properties don’t. Hopefully this post illustrated some tricks to using entity framework and reduce the overall coding needed.