** Update ** EntityFramework detecting complex type with database first

Originally, I posted a question on StackOverflow

http://stackoverflow.com/questions/21630431/entityframework-detecting-complex-type-with-database-first

While we’re still not using complex types, we’ve worked out a mechanism to preventing our developers from breaking the autogenerated models when re-generating from the DB.

We’ve altered the T4 template generated by EF.

First we’ve created a method in the CodeStringGenerator class

public string BaseClassAndInterfaces(EntityType entity)
{
    var properties = new List<EdmProperty>(_typeMapper.GetSimpleProperties(entity));
    bool hasAuditFields = false;
    if (properties.Exists(property => _code.Escape(property) == "CreatedBy") &&
        properties.Exists(property => _code.Escape(property) == "CreatedDate") &&
        properties.Exists(property => _code.Escape(property) == "UpdatedBy") &&
        properties.Exists(property => _code.Escape(property) == "UpdatedDate"))
    {
        hasAuditFields = true;
    }
 
    return string.Format(" : {0}", hasAuditFields ? "Auditable" : "NotificationObject");
}

If it detects that a table contains those auditing fields, then it prepares to generate the class with a base class “Auditable”, which has those four properties. You’ll notice that if we don’t see the auditing properties, we then set the base class to NotificaitonObject. That’s because we’re still using our own variant of the deprecated Prism NotificationObject.

Next in the T4 template, in the class declaration, we do the following.

<#=codeStringGenerator.EntityClassOpening(entity)#><#=codeStringGenerator.BaseClassAndInterfaces(entity)#>

This basically outputs the

public class MyAwesomeAuditableModel : Auditable

Next it gets a bit messy. However, the goal of the following lines is to prevent the T4 template from autogenerating the columns that are already defined in the base class.

var simpleProperties = new List<EdmProperty>(typeMapper.GetSimpleProperties(entity));
if (simpleProperties.Any())
{
    bool hasAuditFields = false;
    if (simpleProperties.Exists(property => code.Escape(property) == "CreatedBy") &&
        simpleProperties.Exists(property => code.Escape(property) == "CreatedDate") &&
        simpleProperties.Exists(property => code.Escape(property) == "UpdatedBy") &&
        simpleProperties.Exists(property => code.Escape(property) == "UpdatedDate"))
    {
        hasAuditFields = true;
    }
 
    foreach (var edmProperty in simpleProperties)
    {
        if (!hasAuditFields ||
            (code.Escape(edmProperty) != "CreatedBy" &&
             code.Escape(edmProperty) != "CreatedDate" &&
             code.Escape(edmProperty) != "UpdatedBy" &&
             code.Escape(edmProperty) != "UpdatedDate"))
        {
#>
<#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }
}

That’s it! Now, we have our dev team, re-generating models all day long, high five-ing and hugging each other all through the days because of how awesomely convenient things are now.

Below is a link to the actual T4 template file that you can play with and see how it’ll impact your generated output classes. If you decide to use it, you will likely have to tweak it, to conform to the conventions in your environment.

http://www.ninjacrab.com/randomcodingdownloads/Example.tt

Keep on coding on!

Leave a Reply