T4 Templates for Entity Framework Break when upgrading to Visual Studio 2012

I upgraded to Visual Studio 2012 and consequently upgraded to version 4.5 of the .NET framework. It turns out, this made our T4 templates very unhappy.

See, we use T4 templates for generating our Entity Framework(EF) models. A bunch of very fancy template coding that automagically creates our edmx and other code files from a reference database.

This worked very well in .NET 4.0, but simply upgrading to .NET 4.5 made it throw all sorts of fun errors.

The root cause turned out to be it was generating EF3 schema data which completely hosed the template code which was looking for EF2 schemas. Not to mention, I tried converting the template processing code to use the new schemas and then realized that since we target .NET 4.0, that we couldn’t compile after the templates worked.

So, I was stuck in a catch 22. Fix the templates, and can’t build the assembly, or only build the templates on a machine with .NET 4.0 and VS 2010. Both options suck.

Well, I reached out into the forums and got a little advice at least on targeting the right framework.

I changed the headers to target 4.0. That turned out to be Step 1.

<#@ template debug=”true” hostspecific=”false” language=”C#v4.0″ #>

<#@ output extension=”.edmx” #>

<#@ Assembly Name=”System.Core, Version=4.0.0.0, Culture=neutral” #>

<#@ Assembly Name=”System.Data, Version=4.0.0.0, Culture=neutral” #>

<#@ Assembly Name=”System.Data.Entity, Version=4.0.0.0, Culture=neutral” #>

<#@ Assembly Name=”System.Data.Entity.Design, Version=4.0.0.0, Culture=neutral” #>

<#@ Assembly Name=”System.Xml, Version=4.0.0.0, Culture=neutral” #>

<#@ Assembly Name=”System.Xml.Linq, Version=4.0.0.0, Culture=neutral” #>

 

Now, step 2. I discovered through hours of staring at code and hoping for hope to find an overload, setting,property or something to say….Damn it, I wan’t EF 2 code. Yeah, you would think running in 4.0 framework mode would do that for me, right? Nothing can be simple.

I finally found it. The overloads I needed.

EntityContainer entityContainer = this.storeItems.GetItems<EntityContainer>()[0];
    this.modelGenerator = new EntityModelSchemaGenerator(entityContainer, ModelNamespace, this.entityContainerName);
    this.modelGenerator.GenerateForeignKeyProperties = true;
    this.modelGenerator.PluralizationService = this.pluralizationService;

    this.modelGenerator.GenerateMetadata(EntityFrameworkVersions.Version2);

Generate MetaData has a Version overload.

So does the schema generator.

  var generator = new EntityStoreSchemaGenerator(this.provider, this.connectionString, ModelNamespace + "." + StoreNamespace);

    IList<EdmSchemaError> errors = generator.GenerateStoreMetadata(this.filters,EntityFrameworkVersions.Version2);

 

So, now we have the fix. All is well in the world. Only lost a day or two of headbanging my screen and yelling at how much T4 is an undocumented piece of crap. Well, it least I have a stronger understanding of it now.

Hopefully this saves you some headache, since not one damn google search result explained this.

Happy Coding!

Unit Test to verify Entity Framework Model (EDMX) is accurate

I work extensively with the Entity Framework in most of my projects. One thing that gets frustrating though is when you work with a large team and the data model gets out of synch with your local database.

You normally don’t figure it out until you are running some operation in your application and get the dreaded Entity Framework error. (inner exception = Column Missing), or non-nullable type, or other enjoyable light reading.

I put together a simple unit test that will work with any model and verify it using a very simplistic technique. It’s a quick smoke test.

 

You will need to modify this code to fit your mechanics for creating the entity context, and the connection strings, etc. Other than that, it is shake and bake.

        [TestMethod]
        public void VerifyModelAccuracy()
        {
            //FYI – When switching to multiple engagements, will need to pass in engagement id for db connection (get from routing db)
            using (var context = EngagementContextFactory.CreateEngagementContext())
            {
                //lazy and dont want to research why this isnt loading
                //use reflection to iterate over each collection in the context and just watch for errors.

                Type t = context.GetType();
                var props = t.GetProperties();
                foreach (var p in props)
                {
                    var isEnumerable = (from i in p.PropertyType.GetInterfaces()
                                        where i == typeof(IEnumerable)
                                        select i
                                            ).Count() > 0;
                   
                    if (isEnumerable)
                    {
                        try
                        {
                            IEnumerable dataToPull = (IEnumerable)p.GetValue(context,null);
                            if (dataToPull != null)
                            {
                                var result = (from object d in dataToPull select d).FirstOrDefault();
                            }
                        }
                        catch (Exception ex)
                        {
                            string error = ex.Message;
                            if (ex.InnerException != null)
                                error += ex.InnerException.Message;
                            Assert.Fail(error);
                        }
                    }
                }               
            }
        }
Happy Coding!!

Using a LINQ compiled query to determine if a record exists with the Entity Framework

I am writing an application that requires high performance on the server layer. The method I am calling will be invoked a large number of times, so I don’t want the overhead of the LINQ compile every time I invoke it.

Yes, the compile is very expensive. It is especially so when called a large number of times in a small timeframe. So, I decided to write a compiled query. It is really quite scary looking at first, but don’t worry. It does get easier once its dissected.

Let’s start by looking at my compiled query.
//precompiling my query to reduce the overhead. grab one field from db, and only first. Should be fastest.
private static readonly Func<MyDataContext,Guid,bool> _CompiledRecordExists =
CompiledQuery.Compile<MyDataContext,Guid,bool>(
(context,myTableID) => ((from record in context.MyTable
where record.myTableId == myTableID
select record.MyTableId
).FirstOrDefault() != null)
);

So I have  a compiled query called _CompiledRecordExists. This query is compiled on when the class static are all instantiated.  We are creating a query which takes in a data context from the Entity Framework, a Guid for the records primary key, and a return value of a bool.

You will notice the Func template/generic which allows us to do this. The last parameter, you can have up to 6 parameters, is the return value of the function.

My linq query is then created in my lambda function. You can see I use the variables context and myTableID. You can name these whatever you want, the order is what is important. The first one is the first type you used in the Func declaration. The second one is the second, so on and so on. Notice there is no bool. That is because its our return value.

In order to actually use our compiled function in code, we need to simply call it. It is really simple now.

using (var context = factory.CreateContext())
            {
                return _CompiledRecordExists (context, recordID);
            }

Notice that we can call it just like a function. Now you won’t have any of the overhead of the sql query generation. The hit was taken up front.

Try running a tight loop on your linq queries and the compiled queries and let me know how it works for you.

Happy Coding!

Entity Framework: The version of SQL Server in use does not support datatype ‘datetime2’

I development against a 2008 copy of SQL Server, which normally isn’t a problem, until….. I pushed out my latest code to the production system, which runs SQL 2005, and started smoke testing the system. As soon as I tried to write a record, i got the data type exception. Its painfully in the innerexception.

So, I think to myself, I am not doing anything amazing here. I am just trying to use the Entity Framework to write simple data. Well, apparently there is a tag in the store model saying what version of SQL you are targeting. Is there an easy property window for this? Nope. Open the XML.

If you change the 2008 out the server version you are targeting. 2005 or 2000 if your old, and voila. Up and running. I guess I need to upgrade the production servers to 2008. What a pain.

Right Click your EDMX file and open with XML Editor. Change ProviderManifestToken=2008 to ProviderManifestToken=2005

Then change the following:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
 <!-- EF Runtime content -->
 <edmx:Runtime>
 <!-- SSDL content -->
 <edmx:StorageModels>
 <Schema Namespace="MyDataModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005"
       xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
       xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
 <EntityContainer Name="MyDBModelStoreContainer">

DataBinding: ‘Telerik.Web.UI.GridInsertionObject’ does not contain a property with the name ‘UserName’.

I use the Telerik controls for a lot of my web work. They save a lot of time but every once in a while they really irritate the hell out of me. A few hours down the rabbit hole and I find that when binding to an EntityDataSource on a RadGrid when trying to insert an item on an empty list. i.e. no records yet, you get the title error.

So, what is the work around? A dummy row on an empty insert. Awesome huh. Well, at least it works.

  protected void dgAuthorizedUsers_ItemCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
    {
        if (e.CommandName == Telerik.Web.UI.RadGrid.InitInsertCommandName )
        {
            e.Canceled = true;
            var newVals = new System.Collections.Specialized.ListDictionary();
            newVals["UserName"] = string.Empty;
            e.Item.OwnerTableView.InsertItem(newVals);
        }
    }

Make sure to add all the different fields you use. So much for declarative programming eh?

Entity framework gives you an error when you add foreign key relationships after you already modeled..

The Entity Framework has a lot of nice features in it for mapping relationships. The bugger is its incessant need for the actual foreign key relationships on the database. Unless of course you like editing XML and never want to use the model wizard again.

So you model your database without the foreign keys, deciding “Ill add those later”. You add them and then run the update model wizard. Cool, the relationships appear but the model doesn’t validate.

Error 20 Error 3007: Problem in Mapping Fragments starting at lines 1586, 2100: Non-Primary-Key column(s) [UserID] are being mapped in both fragments to different conceptual side properties - data inconsistency is possible because the corresponding conceptual side properties can be independently modified.
What to do?

It’s actually easy. Just delete the old keys from the entity. ex. You added the Users table relationship. Well, delete the UserID off the entity.

All done.