T4 Templates for Generating Views for EF4/EF5 Database/Model First apps

After we received a comment on the EF team blog asking why the templates for generating views for Edmx based apps we posted years ago were not updated for EF5 Rowan asked me if I it would be possible to update the template so that it works for EF5. I actually remember looking at this template before I shipped my templates generating views for Code First apps and one of the first things I noticed was that the way it handled versions was robust but not very flexible. Therefore, when we shipped EF5, the templates could not be used with apps using v3 of the EF artifacts (edmx). I thought a bit more about this when I was working on the templates for CodeFirst and concluded that robustness is not really very important here. If someone wants views they will have to provide a valid model (be it Code First model or Edmx) or the APIs used for generating views will throw an exception. Since the exception will be displayed in the error pane (and should be understandable for any person who is trying to use pre-generated views) there was no need to sacrifice flexibility for robustness. Also, the expierence of using the template was not very good. It was posted as a .zip file attached to a blog post. Not only wasn’t it discoverable but you would also have to take a number of extra steps to be able to use it. Visual Studio Gallery makes it much easier to find and use extensions like this, so I thought it was not a bad idea to revamp the template and ship it on the VS Gallery (especially given that I already have all the infrastructure needed to create a shippable .VSIX files containing a T4 templates). The only thing I was missing was the template itself. Luckily(?) I was investigating a bug which I thought could be worked around by using pre-generated views. After I finished up coding the template it turned out that this is not the case (i.e. you cannot use pre-generated views if you have QueryViews in your mapping) but at least I had a T4 template for generating views for Database/Model First apps. Now I only had to marry the infrastructure for building .vsix with the template and call it done (I went a bit further and even created a VB.Net version of the template). Since yesterday the templates are available on Visual Studio Gallery – the C# version can be found here and the VB.Net version can be found here. Using the templates is simple. In Visual Studio right-click on your project and select Add→New Item (Ctrl+Shift+A). In the “Add New Item” window select “Online” on the left. You may want to filter by EF5 or edmx. Select the “EF4/EF5 Model/Db First View Gen .tt for {C#|VB.Net}”. Change the name of the .tt file so that it starts with the name of your edmx file (i.e. if your edmx file is called “MyModel.edmx” name the template “MyModel.Views.tt”) and press the “Add” button:

Add New Item - Edmx Views

Add New Item – Edmx Views


and that’s pretty much it – the template and a class containing views should now be added to your project:
Project with views

Project with views


If you want to enforce re-generating views (e.g. after the edmx file changed) just right click the .tt file and select “Run Custom Tool”.
If you need to uninstall the template go to Tools→Extensions and Updates… select the template from the list and click the “Uninstall” button.

Advertisements

28 thoughts on “T4 Templates for Generating Views for EF4/EF5 Database/Model First apps

  1. Yuyo says:

    Hey Pawel, I’m still having the issue with the View generator. (Yuyo from VS gallery)

    An Exception was thrown while running the transformation code. The process cannot continue. The following Exception was thrown:
    System.Runtime.Remoting.RemotingException: Object ‘/898fa09b_3c37_4ff7_a56a_38d376b9c570/fot3cya6vg4rok_cqtirinsq_117.rem’ has been disconnected or does not exist at the server.
    at Microsoft.VisualStudio.TextTemplating.TransformationRunner.get_Errors()
    at Microsoft.VisualStudio.TextTemplating.Engine.CompileAndRunCode(String generatorCode, ITextTemplatingEngineHost host, TemplateProcessingSession session)

    Like

    • moozzyk says:

      Hi Yuyo,

      This seems like the domain in which the transformation was running crashed. Unfortunately it does not tell me anything about what happened in the transformation app domain. I can suggest a few things to troubleshoot:
      – see event viewer – it may contain some useful information (e.g. exception details, stack trace etc.)
      – play a little bit with the template (e.g. by commenting out parts until you get it working to identify what causes the issue, or by running everything in try catch and returning ex.ToString() from the exception handler)
      – provide me with a repro project and I will investigate if I can duplicate the issue in my environment

      Thanks,
      Pawel

      Like

      • Yuyo says:

        I found that this is also starting to happen to me in other places, like the PM Console. Maybe this helps in shedding some light? What could be happening?

        PM> Enable-Migrations -Force
        Checking if the context targets an existing database…
        System.Runtime.Remoting.RemotingException: Object ‘/fe458313_75e1_46c1_9643_3f5272ba2f1b/uchog3xmqliur6hmf9ms8ny5_2.rem’ has been disconnected or does not exist at the server.

        Server stack trace:
        at System.Runtime.Remoting.Channels.ChannelServices.CheckDisconnectedOrCreateWellKnownObject(IMessage msg)
        at System.Runtime.Remoting.Channels.ChannelServices.SyncDispatchMessage(IMessage msg)

        Exception rethrown at [0]:
        at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
        at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
        at EnvDTE.Project.get_Properties()
        at System.Data.Entity.Migrations.Extensions.ProjectExtensions.GetPropertyValue[T](Project project, String propertyName)
        at System.Data.Entity.Migrations.Extensions.ProjectExtensions.OpenFile(Project project, String path)
        at System.Data.Entity.Migrations.EnableMigrationsCommand.c__DisplayClass2.b__0()
        at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
        Object ‘/fe458313_75e1_46c1_9643_3f5272ba2f1b/uchog3xmqliur6hmf9ms8ny5_2.rem’ has been disconnected or does not exist at the server.

        Like

      • moozzyk says:

        I found this thread on stackoverflow. It explains what is happening but I don’t know how helpful it will be in solving your problem. You may want to take a look at the event log to see if it contains any interesting information. The issue you are seeing seems something bigger than a potential bug in the T4 template since the template itself does not set up AppDomains or using remoting (unless there is a serious bug in the template that causes the AppDomain to crash (would probably have to be a StackOverflowException or an access violation) and trying to access objects that previously lived in the AppDomain that crashed fails) and also you seem to be experiencing it in other places. I also checked code for the stack trace you showed – it appears that it fail when interacting with VS Project – GetPropertyValue in this case is trying to get a full path of your project. Is there anything specific with your path? Do you see the behavior only in one project or the same is happening when you create a new project? The T4 template is interacting with the VS Project as well so there seems to be a common theme to it.

        Like

      • moozzyk says:

        Btw. thanks for pointing out the bug in the template. The bug crept in when I tried to fix the template so that it works with deeper context hierarchies but must have forgotten to test the simplest case after my changes (not being able to write reasonable tests for T4 sucks). I have just uploaded the fixed version to the VS Gallery.

        Like

      • moozzyk says:

        Try the following code in your app:


        var ctx = new MyContext();
        var mappingItemCollection =
        (StorageMappingItemCollection)
        ((IObjectContextAdapter) ctx).ObjectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);

        var errors = new List();
        var views = mappingItemCollection.GenerateViews(errors);

        Console.WriteLine(views.Count);

        this is basically what the view gen template does but since you will be doing this inside your app you should see the exception (if one is being thrown).

        Btw. I think a guy on our team found why it may take a lot of time for an EF app to start under the debugger. Here is the work item to track this: https://entityframework.codeplex.com/workitem/1778.

        Like

      • Yuyo says:

        You’re welcome, glad you got it fixed.

        I tried creating a new project from scratch and the issue is still occurring.

        I tried with a smaller database (2 tables instead of 2000) and the views are getting generated correctly. No error… So this sounds like an issue with large models.

        What do you think?

        Like

      • moozzyk says:

        OutOfMemory exception?

        Like

      • Yuyo says:

        Maybe. I don’t see anything that says it’s an out of memory exception, and the Event Viewer didn’t have any additional info for me.

        I trimmed the model by removing all the entities that mapped to views, and the template finished generating the views. It might be a bug in the EnvDTE stuff.

        Every time my model changes, I should regenerate the views, right?

        Like

      • Yuyo says:

        Do I need to do anything after I generate the views? Like call a method during my app’s startup or anything? They don’t seem to be getting loaded since startup is still slow…

        My DbContext is in MyApp.Models namespace and I added the view generator to the root of my project.

        Like

      • moozzyk says:

        You should not need to do anything special after generating views – if they are part of your project they should be used. To make sure it happens you can set a breakpoint in the GetView method, start debugging with F5 and verify the breakpoint gets hit. EF CodeFirst builds model from your classes when you start your app and it can get expensive for bigger models. Unfortunately EF6 startup time appears to be slower than EF5 startup time. Some of the performance regressions were addressed in EF 6.0.1. EF 6.0.1. was shipped on the same day when Visual Studio 2013 shipped and is the default version adding the EF6 nuget package to your project. However the version of EF that shipped inside Visual Studio is still EF 6.0.0 which does not contain performance fixes included in 6.0.1 so if you happen to use it you should upgrade to EF 6.0.1 – see this for more details (Improving Startup Performance section).

        Like

      • Yuyo says:

        I’ve set my debugger to stop in the views constructor and in GetView, and none of these places are hit.

        My models and context reside in a class library. I am referencing this class library in a console app project, where I’m testing it. The views were generated in the library. Am I doing something wrong?

        Like

      • Yuyo says:

        Actually, I’m sorry. It does hit those places. It just takes a VERY long time (~8 minutes) to get there. Why is that? I assumed this would be the first thing to happen.

        Like

      • moozzyk says:

        CodeFirst need to build a model first. It is quite complicated and uses reflection to discover model so it can be slow. On the other hand 8 minutes is quite excessive. Folks on our team are looking at this (https://entityframework.codeplex.com/workitem/1749) but I would recommend you create a new bug for what you are seeing or comment with your start up time. They will most likely ask you for sharing your model to repro the problem and measure where EF spends most of the time preparing the model. The bug 1749 has a workaround which is to create an Edmx for you model to save the time CodeFirst needs to spend to build it. You can create a model from a CodeFirst app by using EdmxWriter.WriteEdmx.

        Like

    • Yuyo says:

      Maybe. I don’t see anything that says it’s an out of memory exception, and the Event Viewer didn’t have any additional info for me.

      Like

      • moozzyk says:

        I posted a comment (for some reason it was posted above) – it contains a code snippet that will hopefully repro the issue that is happening in the T4 but without remoting and in the same AppDomain. Give it a try and let me know.

        Like

  2. Hey Pawel, is there a way to enforce regeneration automatically when the edmx changes so that I don’t have to do that manually?

    Like

  3. It doesn’t seam to work with VS2010. mappingItemCollection.MappingVersion is internal in .Net 4.0 and public in 4.5

    Like

    • moozzyk says:

      You are right. I no longer have any machine with .NET Framework 4 (as opposed to .NET Framework 4.5) so was not really able to verify this in such a setup. I will take a look what I can do about this. For now you probably could just hardcode the value in your template.

      Like

  4. […] or “T4 TEMPLATES FOR GENERATING VIEWS FOR EF4/EF5 CODE FIRST APPS ” and “T4 TEMPLATES FOR GENERATING VIEWS FOR EF4/EF5 DATABASE/MODEL FIRST APPS […]

    Like

  5. Marcelo L says:

    the Extension as downloaded either from the Extension manager or as a VSIX from CodePlex generates an error, and I’m unable to install into VS2010 SP1.

    I get a “Path too long exception”

    04/28/2014 6:07:21 PM – Microsoft Visual Studio Extension Installer
    04/28/2014 6:07:21 PM – ——————————————-
    04/28/2014 6:07:21 PM – Initializing Install…
    04/28/2014 6:07:22 PM – Extension Details…
    04/28/2014 6:07:22 PM – Identifier : ClassicEFEdmxViewGenT4TemplateCSharp.PawelKadluczka.426e5d58-1d30-4a18-b086-67231a736ce8
    04/28/2014 6:07:22 PM – Name : EF4/EF5 Model/Database First View Gen .tt for C#
    04/28/2014 6:07:22 PM – Author : Pawel Kadluczka
    04/28/2014 6:07:22 PM – Version : 1.0.0
    04/28/2014 6:07:22 PM – Description : C# T4 template for creating pre-generated views for applications using Entity Framework (EF4 or EF5) Model/Database First (Edmx)
    04/28/2014 6:07:22 PM – Locale : en-US
    04/28/2014 6:07:22 PM – MoreInfoURL : https://blog.3d-logic.com/
    04/28/2014 6:07:22 PM – InstalledByMSI : False
    04/28/2014 6:07:22 PM – MinFramework : 4.0
    04/28/2014 6:07:22 PM – MaxFramework : 4.0
    04/28/2014 6:07:22 PM –
    04/28/2014 6:07:22 PM – Supported Visual Studio Editions :
    04/28/2014 6:07:22 PM – Version : 10.0
    04/28/2014 6:07:22 PM – VCSExpress
    04/28/2014 6:07:22 PM – VWDExpress
    04/28/2014 6:07:22 PM – Pro
    04/28/2014 6:07:22 PM – Version : 11.0
    04/28/2014 6:07:22 PM – VCSExpress
    04/28/2014 6:07:22 PM – VWDExpress
    04/28/2014 6:07:22 PM – Pro
    04/28/2014 6:07:22 PM – Version : 12.0
    04/28/2014 6:07:22 PM – VCSExpress
    04/28/2014 6:07:22 PM – VWDExpress
    04/28/2014 6:07:22 PM – Pro
    04/28/2014 6:07:22 PM –
    04/28/2014 6:07:22 PM – Supported Isolated Shells :
    04/28/2014 6:07:22 PM –
    04/28/2014 6:07:22 PM – References :
    04/28/2014 6:07:22 PM –
    04/28/2014 6:07:22 PM – Searching for applicable products…
    04/28/2014 6:07:22 PM – Found installed product – Microsoft Visual Studio 2010 Professional
    04/28/2014 6:07:23 PM – The extension with ID ‘ClassicEFEdmxViewGenT4TemplateCSharp.PawelKadluczka.426e5d58-1d30-4a18-b086-67231a736ce8’ is not installed to Microsoft Visual Studio 2010 Professional.
    04/28/2014 6:09:33 PM – The following target products have been selected…
    04/28/2014 6:09:33 PM – Microsoft Visual Studio 2010 Professional
    04/28/2014 6:09:33 PM –
    04/28/2014 6:09:33 PM – Beginning to install extension to Microsoft Visual Studio 2010 Professional…
    04/28/2014 6:09:33 PM – Install Error : System.IO.PathTooLongException: C:\Documents and Settings\MyUser\Local Settings\Application Data\Microsoft\VisualStudio\10.0\Extensions\Pawel Kadluczka\EF4%2FEF5 Model%2FDatabase First View Gen .tt for C#\1.0.0\T4\Code\ClassicEFEdmxCSharp.Views.zip: ClassicEFEdmxViewsCSharp.vstemplate
    at Microsoft.VisualStudio.ExtensionManager.ExtensionManagerService.BeginInstall(IInstallableExtension installableExtension, Boolean perMachine, AsyncOperation asyncOp)
    at Microsoft.VisualStudio.ExtensionManager.ExtensionManagerService.InstallWorker(IInstallableExtension extension, Boolean perMachine, AsyncOperation asyncOp)

    Any ideas how to modify the package so it doesn’t have to blow up using the “Documents and Settings” Path?

    Like

  6. Marcelo L says:

    04/28/2014 6:22:14 PM – Microsoft Visual Studio Extension Installer
    04/28/2014 6:22:14 PM – ——————————————-
    04/28/2014 6:22:14 PM – Initializing Install…
    04/28/2014 6:22:17 PM – Extension Details…
    04/28/2014 6:22:17 PM – Identifier : ClassicEFEdmxViewGenT4TemplateCSharp.PawelKadluczka.426e5d58-1d30-4a18-b086-67231a736ce8
    04/28/2014 6:22:17 PM – Name : EF4/EF5 Model/Database First View Gen .tt for C#
    04/28/2014 6:22:17 PM – Author : Pawel Kadluczka
    04/28/2014 6:22:17 PM – Version : 1.0.0
    04/28/2014 6:22:17 PM – Description : C# T4 template for creating pre-generated views for applications using Entity Framework (EF4 or EF5) Model/Database First (Edmx)
    04/28/2014 6:22:17 PM – Locale : en-US
    04/28/2014 6:22:17 PM – MoreInfoURL : https://blog.3d-logic.com/
    04/28/2014 6:22:17 PM – InstalledByMSI : False
    04/28/2014 6:22:17 PM – MinFramework : 4.0
    04/28/2014 6:22:17 PM – MaxFramework : 4.0
    04/28/2014 6:22:17 PM –
    04/28/2014 6:22:17 PM – Supported Visual Studio Editions :
    04/28/2014 6:22:17 PM – Version : 10.0
    04/28/2014 6:22:17 PM – VCSExpress
    04/28/2014 6:22:17 PM – VWDExpress
    04/28/2014 6:22:17 PM – Pro
    04/28/2014 6:22:17 PM – Version : 11.0
    04/28/2014 6:22:17 PM – VCSExpress
    04/28/2014 6:22:17 PM – VWDExpress
    04/28/2014 6:22:17 PM – Pro
    04/28/2014 6:22:17 PM – Version : 12.0
    04/28/2014 6:22:17 PM – VCSExpress
    04/28/2014 6:22:17 PM – VWDExpress
    04/28/2014 6:22:17 PM – Pro
    04/28/2014 6:22:17 PM –
    04/28/2014 6:22:17 PM – Supported Isolated Shells :
    04/28/2014 6:22:17 PM –
    04/28/2014 6:22:17 PM – References :
    04/28/2014 6:22:17 PM –
    04/28/2014 6:22:17 PM – Searching for applicable products…
    04/28/2014 6:22:17 PM – Found installed product – Microsoft Visual Studio 2010 Professional
    04/28/2014 6:22:26 PM – The extension with ID ‘ClassicEFEdmxViewGenT4TemplateCSharp.PawelKadluczka.426e5d58-1d30-4a18-b086-67231a736ce8’ is not installed to Microsoft Visual Studio 2010 Professional.
    04/28/2014 6:23:14 PM – The following target products have been selected…
    04/28/2014 6:23:14 PM – Microsoft Visual Studio 2010 Professional
    04/28/2014 6:23:14 PM –
    04/28/2014 6:23:14 PM – Beginning to install extension to Microsoft Visual Studio 2010 Professional…
    04/28/2014 6:23:15 PM – Install Error : System.IO.PathTooLongException: C:\Documents and Settings\mlopezjr\Local Settings\Application Data\Microsoft\VisualStudio\10.0\Extensions\Pawel Kadluczka\EF4%2FEF5 Model%2FDatabase First View Gen .tt for C#\1.0.0\T4\Code\ClassicEFEdmxCSharp.Views.zip: ClassicEFEdmxViewsCSharp.vstemplate
    at Microsoft.VisualStudio.ExtensionManager.ExtensionManagerService.BeginInstall(IInstallableExtension installableExtension, Boolean perMachine, AsyncOperation asyncOp)
    at Microsoft.VisualStudio.ExtensionManager.ExtensionManagerService.InstallWorker(IInstallableExtension extension, Boolean perMachine, AsyncOperation asyncOp)

    I see it’s getting a “Path too long Exception”, butis there no way for this to not use that path?

    Like

    • moozzyk says:

      Hi Marcelo,

      I did install this vsix on a couple of boxes but have never seen this error and so far no one has reported it. Interestingly the path it is complaining about has less than 170 characters and the system limit is about 255 characters so I am not sure why this is happening. I wonder if this has anything to do with the path VS is installed. For now to workaround the issue you can download the vsix and change the extension to “zip” then you will be able to find the `ClassicEFEdmx.CSharp.tt` file in ClassicEdmxViewGenT4TemplateCSharp.vsix.zip\T4\Code\ClassicEFEdmxCSharp.Views.zip folder which you need to just add to the project. You can also get the file from my github repo – https://github.com/moozzyk/EF5EdmxViewGenT4Templates/tree/master/EF5EdmxViewGenT4TemplatesCSharp/PayloadUnzipped. Hope this helps.

      Pawel

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: