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

Advertisements

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.

ASP.NET MVC Dynamic Reference Data Loading

MVC, like any other language, is a tool that has plenty of capabilities when rendering client markup; one method call can render pages of client markup. Using a server-side approach can simplify some of the rendering of content needed. As a for instance, here is one common situation I often use a server-side approach to rendering content within an application. An application may have a Kendo DropDownList, which is highly dependent on a list of some data in JSON format. The initialization script looks like the following:

$("DropDownList").kendoDropDownList({
   dataSource [{ .. }],
   dataTextField: "Text",
   dataValueField: "Value"
});

Typically, the data source is some lookup data source; in most applications, lookup data typically contains a key and value. The dataTextField and dataValueField properties map to values within these It’s helpful to have lookup data that’s standardized, because it’s easy to create a helper function that does the following:

@Helper LookupData(IList data)
{
   return NewtonSoft.JSON.JsonConvert.SerializeObject(data);
}

This helper converts data to JSON, which is used in the script below.

$("DropDownList").kendoDropDownList({
   dataSource @LookupData(Model.CustomerTypes),
   dataTextField: "Text",
   dataValueField: "Value"
});

Here we take a collection of reference items and use that to convert it to JSON. Really, that approach may not be that useful, but where you can find use is if you have a common reference table loader object. Using this, the helper function can automatically retrieve a common dataset based on a given type of reference data:

@Helper LookupData(Type referenceType)
{
    var container = Framework.Container; // this is a singleton reference to the dependency injection container
    var referenceData = container.GetInstance(); //A utility class to load common reference data

    return JSONConvert.DeserializeObject(referenceData.GetValues(referenceType));
}

The reference data uses an IReferenceTableManager class to perform the work. Behind the scenes, this could be anything, including Entity Framework. Below is one possible solution:

public class ReferenceValue
{
    public int ID { get; set; }

    public string Text { get; set; }
}

public interface IReferenceTableManager { 
   IEnumerable GetValues(Type type);
}

public class EFReferenceTableManager : IReferenceTableManager {
  public IEnumerable GetValues(Type type)
  {
     var ctx = new EntityFrameworkContextInstance();

     //From a given type, there are multiple ways to get the data from the DB; I am not
     //aware of a way to query by type (at least easily). There may be a better way to do this,
     // but for the time being, the two possible ways to do query referenced data dynamically
     //by generics are: using reflection or, using a long if statement and type checking like:
     if (type.Equals(typeof(Countries))) {
       return ctx.Set().ToList();
     }
     else if (type.Equals(typeof(States))) {
       return ctx.Set().ToList();
     }
     .
     .
  }

}

Not the best implementation; I’m sure there is something better out there, but you get the idea as to how this dependency can now be implemented dynamically. However, the question most will have is whether this is scope creep on behalf of the view (as to whether this is a responsibility of the controller). It’s also possible to have the lookup helper examine a given model and extract the data from there too. There are multiple ways to solve this problem.