Entity Framework Code First View Generation Templates On Visual Studio Code Gallery

Some time ago I created T4 templates for creating pre-generated views for Entity Framework Code First applications. I wanted to make them available as soon as possible so I just uploaded them as a zip file to one of my sites and provided a link. This worked as a short-term solution but long-term I wanted something better. Something that would not require manual work. Something that would integrate with Visual Studio seamlessly. Something that is actually called Visual Studio Code Gallery. And it happened yesterday. Yesterday I published the templates on the Visual Studio Code Galery.

Using the templates

First you need to download the templates. You can do it directly from Visual Studio. Right click on your project and select Add -> New Item (Ctrl+Shift+A). In the Add New Item dialog go to “Online templates”:

Add New Item - Online Templates

and search for “EF Views”. This should make the “EF CodeFirst View Generation T4 Template for C#/VB” show up (note: only the template for the language of the current project will show up).

Add New Item - Search Templates

Change the name of the file at the bottom to {Context}.Views.tt where {Context} is the name of the class derived from DbContext you want to create pre-generated views for.
Click “Add” to add the template to your project. Wait for the views to be generated (note: for bigger models view generation may take an extended amount of time).

You can also install templates manually just by downloading vsix files from Visual Studio Code Gallery and pressing “Enter”. Here are direct links to the templates:

Once you installed the templates you can find them in the “Code” category. Right click on your project and select Add -> New Item (Ctrl+Shift+A). In the “Add New Item” dialog go to the “Code” section:

Add New Item - Using Installed Templates

If needed the templates can be uninstalled from Extension Manager (Tools -> Extension Manager):

Unistalling Templates

Happy coding.

Pawel Kadluczka

98 thoughts on “Entity Framework Code First View Generation Templates On Visual Studio Code Gallery

  1. Hi Pawel! So, I am trying this out, and I got it to generate. However, I don’t actually see any performance improvement. It generates ~900 views, and I rebuild (the .Views.cs is definitely in the same project as the context and actually being built so forth). But it takes ~40s seconds to run that first (trivial) query regardless of whether the .Views.cs is compiled in or totally commented out. So — how does EF (v4.3.1 right now) find the precompiled views, and how can I verify that it’s matching up?

    Thanks!

    Like

    1. There are two hashes in the pre-genereated view. Entity Framework will calculate hash of the model and will compare this hash with the hash from the generated view. If hashes match the generated view will be used otherwise an exception will be thrown. One easy way to verify if your pre-generated views are being used is to set a breakpoint in the GetViewAt() method and run the program under debugger. If the views are used the breakpoint will be hit. With 900 views I would expect that the models is quite complicated and generating views would be time consuming. As a result using pre-generated views should help with the app start up time. If you confirm that your pre-generated views are being used take a look at how long it takes to connect to the database. Also if you use advanced mapping strategies (inheritance, entity splitting) and/or your query is complicated it may take a while to compile the first time it is run. Finally, you should check how long it takes to execute the generated SQL query in the database to make sure that this is not the database that is a bottleneck here.

      Like

      1. moozzyk: I’m on the same project as ses4j, also attempting to set up the view generation. It’s not hitting the breakpoint in GetViewAt(), nor is it throwing an exception. Are there any further steps we can take to troubleshoot? Is there more to EF finding the views that we may not be aware of? Thanks for the help!

        Like

      2. Unfortunately I haven’t been able to reproduce it with anything but our current library that hosts the context. What I *have* been able to figure out, is that our context will not use the view only if it is being referenced in a web application. I set up a small EF Code First test library with only a single context and an entity. I referenced that library in a console app, and in a web application, and the views generated for it work in both. I then switched the console app to use our actual library, and the views are being picked up there and work fine. Then I switch the web application to use our library, and in this case, the views are not picked up. I can’t find anything seemingly obvious about our library that differs from the test EF library, so I’m stuck at this point.

        Like

      3. We found it! It appears to search for pregenerated view classes in the assembly of the first DbSet entity listed in the DbContext, rather than in the assembly of the DbContext itself. We keep our (POCO) entities in a separate assembly from the DbContext, so it wasn’t finding it. I added a fake stub entity as the new first entry and the pregenerated views kicked in. Our app startup times went from over 70 seconds to ~18 seconds, a big difference! … why can’t each view be generated on demand instead of “pregenerated” all at once upon first context usage — then all these hoops wouldn’t be necessary!

        Like

    2. Hi Scott,

      can you give me the steps to solve this issue?

      “We found it! It appears to search for pregenerated view classes in the assembly of the first DbSet entity listed in the DbContext, rather than in the assembly of the DbContext itself”

      I ran into the same situation.

      Thank you

      Like

  2. This is great.. somewhere along the long route of building out my project PowerTools would no longer create my pre-gen views, would just error out. Have been tinkering for a fix on and off for awhile with no success. I used this and views were created no issue and I’m back in biz. Really appreciate your work here!

    Like

  3. Hi.
    I’m using a custom build of EF6 sources. The problem is that the generated view is not usable by EF6. The viewcontainer class belongs to a different assembly and namespace than what EF expects. By changing them, EF complains that the view belongs to an outdated mapping. I could not find a class equivalent to EntityViewGenerator in EF6 source to use in the t4. FYI, I’m using .Net4, but I don’t hold on to it, if it’s the problem I can change my server to use .Net 4.5.

    Thanks

    Like

    1. I will look at view generation for EF6. I thought EF5 views would work but have not tried. From what you are saying EF5 views won’t work. This may require opening some APIs that are not public now since I don’t think that the System.Data.Entity.Design.dll will be updated to work with EF6.

      Like

      1. Just a quick guess: System.Data.Entity.Design.dll is for EF4, EF5 on .Net4 uses the EF4 runtime, so the views are compatible. Did you check EF5 on .Net4.5?

        Like

        1. Technically views is just a bunch of ESQL queries describing your database in an abstract way (i.e. in the way that is independent from the actual database). Unless you change your SSDL the ESQL queries should not change. Even if you change runtime from .NET Framework 4 to .NET Framework 4.5 the queries will continue to work (I checked this). In EF6 so far there has not been any changes to the way the views are generated or to the mapping layer (EF6 uses v3 of CSDL, MSL and SSDL) so the ESQL generated for EF6 should be the same. The only thing that may needed to be fixed is the actual code generated by the System.Data.Entity.Design.dll (e.g. namespaces) so that the views could be loaded by EF6.

          Like

  4. couldnt you just please generate edmx the edmx stuff, build and compile metadata and embed in the assembly where dbcontext resides in ? is it just visual studio integration preventing you doing this or there is a (easy) manual way of doing this?

    Like

    1. These T4 templates are for CodeFirst approach. In CodeFirst approach there is no EDMX file exposed to the user. Rather than the model is built at runtime based on the classes (entities) used by your DBContext. If you need T4 templates for Model or Database First you can take a look here: http://blogs.msdn.com/b/adonet/archive/2008/06/20/how-to-use-a-t4-template-for-view-generation.aspx. These are pretty old so you will probably have to account for newer versions of Entity Framework.

      Like

  5. yes those are for codefirst approach, but what im trying to say is, rather then building model at runtime based on classes, this could be done one time by developer, save the resulting edmx and compile&embed them in the assembly. then those assembly will be distributed to client machines. i think we %100 agree that client machines arent responsible for manuplating database schema. only developer. so developer will still take advantage of the precious and time saving code first approach without disturbing client performance.

    Like

    1. What you are talking about is already possible with Model First and Database First approaches (note that once you create a database from your model the first time there is no longer any difference between model and database first). The question however I would like to ask is how an embedded edmx is a stronger contract than object model (classes)? Why should I even have to understand edmx (have you ever tried codin independent associations manually across CSDL, MSL and SSDL – I have and it was not fun)? I would even say that in the scenario you are describing CodeFirst may actually even be safer to use than ModelFirst/DatabaseFirst. Here is the reason – when building an app you allow the app to change the database schema. However when the app is deployed and running in production you don’t want that. To support above scenarios CodeFirst saves in the database the database model that is corresponding to your object model. Now, if you change your object model in a way that requires changing the database EF will throw an exception saying that models (i.e. what was saved in the DB and what is generated from your object model) are not compatible. As a result you won’t be able to run an outdated instance of your application against a newer version of the database (or a newer version of your app against an older version of the database). If you look at model/database first approaches the edmx file lives in the assembly and there is nothing to cross check if it matches your database schema. As a result if you change your model (and as a result the database) all versions of applications will continue to run against a database that is no longer compatible happily throwing unexpected exceptions or potentially overwriting data.

      Like

      1. i disagree with you because i want to use codefirst as im developing the model as a db generation tool. i want to define properties rather then columns. but when it comes to deploying “and upgrading” i dont want the code first to calculate and check model hash, because “i will provide the latest assemblies containing models by myself”. and yes, i will simply compare a integer version number stored in the database at “login”. (which is practically not much different what code-first does). when it comes to upgrading, ill take production database and webserver offline, send to the rich clients shutdown command, make required schema changes, increment version number and done. in next startup rich client will auto-update itself.. but the new assemblies will contain updated edmx. i think this is the same thing as with pure code-first approach. am i right or confused?

        Like

        1. You can do this today. Develop your app with CodeFirst and migrate your database as much as you want when you are developing it. For production environments set the DbInitializer to null (or write your own as you see it fit). This way CodeFirst apps won’t check whether the model and the database are in sync but will blindly write data to the database. (I still believe that having a check that makes sure that you don’t write to an outdated database is useful but maybe it’s just me.) Now, I still don’t really get why you talk about edmx and why you need it. EF is an ORM so it maps objects to a database and vice versa. If you update your edmx file but won’t update your classes nothing will work – EF will throw an exception saying that it cannot find a valid O-C mapping. Edmx and your classes must be in sync. Why not generate edmx from classes then (which is basically what CodeFirst does)?

          Like

  6. if i set DbInitializer to null, will it take 0ms to get code-first domain model ready? i think no and thats why i want compiled edmx in my assembly. and i know i can generate edmx from dbcontext, but i dont want to do same thing over and over when developing models, i dont certanly want two seperate assemblies one for development and one for deployment because when i add-modify single column.i would have to regenerate, compile and embed edmx manually which makes most of advantages of code-first go away.. so my suggestion would be if a special build constant is present embed the compiled model into the assembly.

    by the way, what you are doing with view generation is not much different i think. it also
    “will throw an exception” and must be in synch. so why automating view generation but not compiled edmx generation?

    Like

    1. I have never measured how much time it takes to convert object model to edmx but I would assume it’s negligible if you compare it to most database queries. Even if you have just the Edmx file it needs to be processed to build an internal object representation (i.e. metadata workspace) – so you won’t have 0 ms anyways. In fact Edmx here is just an implementation detail. The problem is that ObjectContext only accepts models in form of Edmx. DbContext is built on ObjectContext and is using only public APIs and therefore it has to create edmx files to be able to leverage EF core components. I could see opening the metadata layer in the future what would enable creating the object model without using edmx files at all. In an ideal world DbContext would share the same metadata object model with ObjectContext and no conversion would be needed.
      Views are a bit different than generating models from classes. While the time for generating Edmx for a given model depends more or less linearly on the model size there is no such a dependency in case of views. I saw models for which view generation took literary tens of minutes. In my view people should not even know what views are and that EF is using views let alone having to generate the views by themselves (either using T4, Power Templates or EdmGen). Having said that – at the moment view generation problem is relatively hard to fix and therefore we have the above workarounds. It’s always the best to have a fix but if there is no fix it’s better to have a workaround to a problem than just a problem.
      To sum up – pre-generated views are a workaround to a nasty problem that is hard to fix, while generating metadata from classes (be it in form of Edmx or any other form) is a designed and intentional behavior.

      Like

      1. didnt the guy say their startup time went from 70sc to 18sc? getting object context from a fresh dbcontext (thus forcing to generate metadataworkspace) blocks the thread reasonable time in my tests even with 3-4 tables. so im not familliar with your jargon but caching compiled model-metadataworkspace-edmx whatever would be great and im not sure but i think also makes pregenerating views unnessesary.

        Like

    2. @ManualGuest. And you point out that you take the production database offline. This is virtually impossible in many mission-critical applications. What we do is finding an upgrade to the database that does not break existing code, we keep the existing server and clients running and start another server instance. Any new client session will be upgraded and redirected to the new server. After the last user logs off the old client, we close the old server. We, also prevent EF from modifying structure of the production database. Additionally, we prevent EF from modifying the development DB as well, it is designed by DB professionals, not as an implication of changes in classes. Maybe it’s me, but I don’t expect any mission-critical large-scale system to use automatic database schema change.

      Currently most of the time is spent preparing the views, not the EDMX. I’ve even pinpointed the slow part and did a hacky code change in ViewGenContext.CreateConstraintsForForeignKeyAssociationsAffectingThisWarapper() (most probably it only works for us) and cut the total server startup time from 80s to 20s, which is totally acceptable (for now). So until this is fixed, I believe Edmx should be considered as a minor issue.

      Like

      1. what do you do if old clients write new data until they are disconnected? even banks and similar systems take their system offline when upgrading. say it at midnight or midday but they do it.

        Like

        1. I should give you an answer for each scenario, sometimes it actually becomes impossible, or too difficult to carry out, but most of the times, something simple.
          For instance, consider you’ve added a basic info table and a foreign-key to it in an operational table. What do you do with old data? If you keep this column null, then you’re good to go: old clients and old server do not insert this field. You set old data to a default value and make this field non-nullale? set a default value for this field so old clients are still happy. The next day you can remove this default value.

          We, too, sometimes need to take the system offline, but it’s much better if this is kept to a minimum,

          Like

  7. i dont know why but there is no reply button under moozzyk’s answer.

    i know its because of view generation, but 17sc is still for edmx generation i think. if not, if it takes under 2sc 1000tables then its ok. i could queue a new threadpool thread at the first line of main method and force objectcontext creation early.

    i have another question, is there much performance difference between having 10 or 1000 tables in the context for the same query/update?

    Like

    1. Yeah, I noticed the lack of reply button when you get to some deep levels of replies!
      In my experience, except the initial burdens, EF does not get slower while you increase the number of entities. One important exception is TPT inheritance in which it creates huge queries, especially as you increase the hierarchy size. Except that, everything is OK.

      Like

      1. thats great news for me because the system im building ideally would contain 6000 tables. there is no inheritence, no complex properties, no implicit many-to-many or foreign key properties, all primary and foreign keys are single column.can i split as much table as i can without doubt? how bad would go initialization of a query at basic or modorate complexity?

        Like

        1. Well… In the current situation of EF (I mean view generation) I expect 6000 tables to be totally out of reach. The msdn page titled “Performance Considerations (Entity Framework)” it is emphasized that it’s an exponential-time algorithm in the worst case. Experimentally, our 300 table with lots of inheritance and navigation properties took 80 seconds in the original code base while their own database with 1000 tables took more than an hour. For 6000 tables I expect that view generation will be so long that even having to pre-generate it will stop you from doing anything.

          So, my suggestion is: if you’re able to break the system to several nearly independent subsystems, each with less than 1000 tables then you may be comfortable with EF, otherwise, not.

          Like

    2. Hi ManualGuest
      Despite my previous, disappointing answer, I now have good news for you. I found a way to improve the view generation speed. In out own project, it changed from 67 sec to 4 sec. The first thing that I had to do was to tell you about that. EF has a great, clean, easy to understand, and easy to modify code base. I’m now more than happy that problems in other ORMs forced me to use EF. I expect this change to appear in the nightly builds in a few days.

      Like

      1. Yes, but in terms of functionality already present in EF5, I only expect bug fixes and improvements. In addition, you get the extra bonus of being open source, which means you can find the real source of the error you get and even make a fix for yourself and/or the others. When we decided to refactor our project to code first, we also changed from EF4 to EF5 and had lots of problems. By downloading the source of EF6, we were able to solve all. One was reported, one improvement was suggested, and I plan to open a discussion on another, so we’ll be able to use the more recent code changes.
        Even once we faced a very strange error in query execution and only falling back to the source helped us find the cause (which was not EF at all, but the error message was not expressive).
        So, my experience with EF6 is that (again, if you plan to use only the functionality present in EF5) you’ll only be happier.

        Like

  8. hi,my app is n-layer and i added t4 template in DataLayer,but that display this error:

    Error 4 Running transformation: System.Data.ProviderIncompatibleException: An error occurred while getting provider information from the database. This can be caused by Entity Framework using an incorrect connection string. Check the inner exceptions for details and ensure that the connection string is correct. —> System.Data.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string. —> System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
    at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover)
    at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover)
    at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
    at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
    at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions)
    at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
    at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
    at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
    at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
    at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
    at System.Data.SqlClient.SqlConnection.Open()
    at System.Data.SqlClient.SqlProviderServices.UsingConnection(SqlConnection sqlConnection, Action`1 act)
    at System.Data.SqlClient.SqlProviderServices.UsingMasterConnection(SqlConnection sqlConnection, Action`1 act)
    at System.Data.SqlClient.SqlProviderServices.GetDbProviderManifestToken(DbConnection connection)
    at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
    — End of inner exception stack trace —
    at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
    at System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection)
    — End of inner exception stack trace —
    at System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection)
    at System.Data.Entity.ModelConfiguration.Utilities.DbConnectionExtensions.GetProviderInfo(DbConnection connection, DbProviderManifest& providerManifest)
    at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
    at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
    at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
    at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
    at System.Data.Entity.Internal.LazyInternalContext.get_CodeFirstModel()
    at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
    at Microsoft.VisualStudio.TextTemplating6DCA48C3204ECFB77AD5004A3510DEC15D1FF0F942E8F4F375752317C0410DD6B3FB27C81753AB1431230B3095F221519737999910AC01E1C9C0F9F9EE5CDEA9.GeneratedTextTransformation.GetEdmx(Type contextType)
    at Microsoft.VisualStudio.TextTemplating6DCA48C3204ECFB77AD5004A3510DEC15D1FF0F942E8F4F375752317C0410DD6B3FB27C81753AB1431230B3095F221519737999910AC01E1C9C0F9F9EE5CDEA9.GeneratedTextTransformation.GenerateViews(String contextTypeName)
    at Microsoft.VisualStudio.TextTemplating6DCA48C3204ECFB77AD5004A3510DEC15D1FF0F942E8F4F375752317C0410DD6B3FB27C81753AB1431230B3095F221519737999910AC01E1C9C0F9F9EE5CDEA9.GeneratedTextTransformation.TransformText() D:\p\pp.DataLayer\ppContext.Views.tt 1 1 pp.DataLayer

    what is cause of this error?

    Like

    1. EF was not able to connect to the database – you can see this in the satcak trace: System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces
      Do you have problems running your app without the T4 template? I tried the T4 template to make what the application does so I would expect you to have similar problems when you run your app. If you don’t have any problems like this – how do you initialize your DbContext and open the connection?

      Like

    1. The “tool” is basically a T4 template (i.e. the .tt file). VisualStudio knows how to process this file and you don’t need to install anything else to make it work. Just follow the steps – add the template to your project (add new item) and it should generate views when you build your project. It can also generate views on demand when you rightlick the template and select “Run custom tool” from the menu. Finally it should also generate views if you change the contents of the .tt file and save your changes (all above applies to any T4 template/.tt file). The exception you posted shows that you did one of the above and the template did not work for you. Since the source of the exception is a problem with connecting to the database and you are able to run your app without problem I assume you have some additional logic in your app for connecting to the database that was not duplicated in the T4 template. I wonder what it is. The template basically creates uses the config file of the app and creates a DbContext instance. So, in your app – how do you initialize your DbContext and open the connection? Do you do anything special?

      Like

      1. i use n-layer app with unit-of-work and repository pattern and IOC.

        i must add T4 template in web(ui) layer Or DataLayer Or DomainLayer?

        Like

        1. To the layer where you have the class that derives from DbContext (I assume it’s DataLayer) – I think you did it since the template was able to call into the EF stack but was not able to connect to the database. I assume it did not use the correct connection string or you have more than ctor on your DbContext-derived class and the T4 template used the ctor that for some reason does not work (e.g. the parameterless which may cause connecting to a local SqlExpress database which does not exist)

          Like

  9. connection string exist in web.config of UI Layer and i add T4 template in DataLayer,
    and in my DataLayer i have a BaseContext which inherited from DbContext and my app context inherited from BaseContext.

    Like

    1. ‘connection string exist in web.config of UI Layer and i add T4 template in DataLayer’ – probably this is the problem. The T4 templates only copies the config from the current project. You may want to change this line in the T4 template EdmxWriter.WriteEdmx((DbContext)Activator.CreateInstance(contextType), writer); to pass the connection string. You would use the overload that allows passing parameters: http://msdn.microsoft.com/en-us/library/wcxyzt4d.aspx

      Like

      1. i copied T4 template in ui layer,now that display this error:
        Running transformation: System.InvalidOperationException: Could not find the context type. Make sure the template name is using convention ‘{ContextTypeName}.Views.tt’
        at Microsoft.VisualStudio.TextTemplating12FE7562C614CB445E56AA3722D6AE17A561647F74CF1625F60A6283BAA632A4EB908FC9EA7642C6535952E8E3D5C439C2C65DE7191C7315B1BAEA231268F960.GeneratedTextTransformation.GetContextType(String contextTypeName)
        at Microsoft.VisualStudio.TextTemplating12FE7562C614CB445E56AA3722D6AE17A561647F74CF1625F60A6283BAA632A4EB908FC9EA7642C6535952E8E3D5C439C2C65DE7191C7315B1BAEA231268F960.GeneratedTextTransformation.GenerateViews(String contextTypeName)
        at Microsoft.VisualStudio.TextTemplating12FE7562C614CB445E56AA3722D6AE17A561647F74CF1625F60A6283BAA632A4EB908FC9EA7642C6535952E8E3D5C439C2C65DE7191C7315B1BAEA231268F960.GeneratedTextTransformation.TransformText()

        Like

        1. You cannot copy it to UI layer since there is not DbContext derived class there. The exception message is clear about that: Could not find the context type. Make sure the template name is using convention ‘{ContextTypeName}.Views.tt’. This exception is thrown by the template and you can find it there. The template has to be in the project where the DbContext derived class lives. Btw. why do you need this template? Do you see issues with your app without it?

          Like

        1. If you want to hardcode a connection string you would have to change this line EdmxWriter.WriteEdmx((DbContext)Activator.CreateInstance(contextType), writer); to use the ctor that takes string and pass the connection string (or the name of the connection string in the form “Name={connectionStringNameFromConfig}”) as the argument

          Like

      2. I am having same error above that.Can you explain how to overload above method with connection string by using example code.

        Like

  10. even with pregenerated views, empty database and simple entities like Country,Region,City,District & Company, CompanyUser it takes at least 4sc to run first query. so why dont you provide a way to embed compiled model into assembly?

    Like

    1. I am not convinced that in this case the query gneration causes the problem. Obviously without profiling the app I cannot tell but I have a feeling that opening the connection to the database for the first time is causing the delay…

      Like

      1. var start = DateTime.Now;
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();
        var ctx = new MainDbContext();
        var t1 = sw.ElapsedMilliseconds; // 142ms
        sw.Restart();
        ctx.Database.Connection.Open();
        ctx.Database.Connection.Close();
        var t2 = sw.ElapsedMilliseconds; // 241ms
        sw.Restart();
        ctx.Database.Connection.Open();
        ctx.Database.Connection.Close();
        var t22 = sw.ElapsedMilliseconds; // 0ms
        sw.Restart();
        var octx = (ctx as System.Data.Entity.Infrastructure.IObjectContextAdapter).ObjectContext;
        var t3 = sw.ElapsedMilliseconds; // 2578ms
        sw.Restart();
        ctx.Countries.Load();
        var t4 = sw.ElapsedMilliseconds; // 81ms
        var end = DateTime.Now; // end – start = 3sec

        Like

  11. public class Country
    {
    public int Id { get; set; }
    public string CountryName { get; set; }
    public ICollection Regions { get; set; }
    }

    public class Region
    {
    public int Id { get; set; }
    public int RegionName { get; set; }
    public int CountryId { get; set; }
    public Country Country { get; set; }
    public ICollection Cities { get; set; }
    }

    public class City
    {
    public int Id { get; set; }
    public string CityName { get; set; }
    public int RegionId { get; set; }
    public Region Region { get; set; }
    public ICollection Districts { get; set; }
    }

    public class District
    {
    public int Id { get; set; }
    public string DistrictName { get; set; }
    public int CityId { get; set; }
    public City City { get; set; }
    }

    public class Company
    {
    public int Id { get; set; }
    public string CompanyName { get; set; }
    public ICollection Users { get; set; }
    }

    public class CompanyUser
    {
    public int Id { get; set; }
    public string Name { get; set; }
    public int CompanyId { get; set; }
    public Company Company { get; set; }
    }

    public class OperatorUser
    {
    public int Id { get; set; }
    public string Name { get; set; }
    }

    Like

  12. my actual ingenious model has different things into it but this pseudo model in a console application yielded 1600ms. i couldnt figure out what makes it different but still 1600ms is considerable time and you can easly test it with

    public class MainDbContext : DbContext
    {
    public DbSet Countries { get; set; }
    public DbSet Companies { get; set; }
    }

    Like

    1. Thanks for the model. I run and this is how the numbers look like on my box:
      Start: 10/29/2012 6:53:58 PM
      t1: 41
      t2: 93
      t22: 0
      t3: 764
      t4: 12
      end: 10/29/2012 6:53:59 PM
      Press any key to continue . . .
      They are smaller than what you had but the relations are similar. I also took a perf profile to see what takes the most time when initializing the context – almost 50% is taken by creating and configuring the model while the other 50% of time is used to detect whether the model has changed (it requires a trip to the database). Here is the screenshot of the profile https://moozzyk.files.wordpress.com/2012/10/perf.png. You could try to remove the consistency check (by setting the DbInitializer to null) what would save you probably 50% of time spent in the initialization but you would not know if database has changed. It’s your call. Obviously for CodeFirst it is not possible to disable the phase of model generation and configuration.

      Like

      1. “Obviously for CodeFirst it is not possible to disable the phase of model generation and configuration.”

        nope, if you provide an entity framework connection string, you can prevent model generation and configuration

        Like

    1. Can you provide more details? Just in case {Context} means you need to provide the name of your DbContext derived class – e.g. if your DbContext derived class is called MyContext the name of the template should be MyContext.Views.tt

      Like

      1. It’s automatic access the views optimized? My question is, just the fact MyContext.Views.cs have already vai optimize loading?

        Thank you.

        Like

        1. EF will look for assembly level EntityViewGenerationAttributes. If it finds any it will read the names of the types that contain views and will load the views. If you are not sure if your views are being loaded/used you may set a breakpoint in the GetViewsAt() method. It should break when the first query is processed by the EF. If you can query a database and get a result but the breakpoint does not break it means that for some reason your pre-generated views are not being used. Note that views are useful if your model is big and/or complicated. For smaller models you will not see a noticeable difference. Also, there is a lot of things happening when an EF app starts – like connecting to a database. If you don’t see any improvement in the start time of your application even after you added your pre-generated views you may need to look at these. The performance considerations paper (http://msdn.microsoft.com/en-us/data/hh949853) is a good starting point to troubleshoot this kind of issues.

          Like

  13. “You are right. I was not aware of this but this without this it would not be possible to use DbContext for Model and Database First workflows in VS2012. ”

    there wasnt reply button.. so, i think code first approach has great share compared to model and database first workflows, even not in green field development, i would choose code first

    Like

  14. Getting a compiling transformation error: “DbContext” is ambigious in the namespace System.Data.Entity.

    There is no conflict in the project for the namespace
    I am using EF 4.4.

    Any help?

    Like

    1. I have not seen this error before. Please provide more details like the target .NET Framework version, language (C#/VB.NET), which template did you try to use etc.. If you can provide a minimal repro in form of a project that I could try it would be awesome.

      Thanks,
      Pawel

      Like

      1. .NET Framework 4.0
        VB.NET
        EF Code Firts Pre-generated Views Generator for VB

        As for the example project I will try to work on it if I cannot figure this out today..

        Thanks in advance…

        Like

    1. Ok So I have gotten past this error, the project was upgrading from the 2011 June CTP EF 4.2 version and I have completely uninstalled this install. Now I am getting a Parameterless constructor defined for the context but at least it is moving forward….

      Like

  15. Ok So I think I almost got it now…

    IT seems to want to connect to a SQL database in order to generate the views? Is this normal for a Code first scenario? Shouldn’t it just read off of the model class the structure to generate?

    Exception:

    Error 2 Running transformation: System.Data.ProviderIncompatibleException: An error occurred while getting provider information from the database. This can be caused by Entity Framework using an incorrect connection string. Check the inner exceptions for details and ensure that the connection string is correct. —> System.Data.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string. —> System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
    at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover)
    at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover)
    at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
    at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance)
    at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions)
    at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
    at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
    at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
    at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
    at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
    at System.Data.SqlClient.SqlConnection.Open()
    at System.Data.SqlClient.SqlProviderServices.UsingConnection(SqlConnection sqlConnection, Action`1 act)
    at System.Data.SqlClient.SqlProviderServices.UsingMasterConnection(SqlConnection sqlConnection, Action`1 act)
    at System.Data.SqlClient.SqlProviderServices.GetDbProviderManifestToken(DbConnection connection)
    at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
    — End of inner exception stack trace —
    at System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection)
    at System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection)
    — End of inner exception stack trace —
    at System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection)
    at System.Data.Entity.ModelConfiguration.Utilities.DbConnectionExtensions.GetProviderInfo(DbConnection connection, DbProviderManifest& providerManifest)
    at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
    at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
    at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
    at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
    at System.Data.Entity.Internal.LazyInternalContext.get_CodeFirstModel()
    at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
    at Microsoft.VisualStudio.TextTemplating8353C377869B03FF065EA08ACF68ABB6.GeneratedTextTransformation.GetEdmx(Type contextType)
    at Microsoft.VisualStudio.TextTemplating8353C377869B03FF065EA08ACF68ABB6.GeneratedTextTransformation.GenerateViews(String contextTypeName)
    at Microsoft.VisualStudio.TextTemplating8353C377869B03FF065EA08ACF68ABB6.GeneratedTextTransformation.TransformText()
    at Microsoft.VisualStudio.TextTemplating.TransformationRunner.RunTransformation(TemplateProcessingSession session, String source, ITextTemplatingEngineHost host, String& result) 1 1

    Like

      1. Glad to hear you were able to resolved it.
        To answer your previous question – in EF5 generating views does require connecting to the database. The reason for this is that views are generated based on C-S (conceptual to store) mapping which requires loading both conceptual and store model. However to load the store model we need a provider manifest token (you can think of it as of a version of a database – e.g. the provider manifest token “2005” indicates you are connecting to the Sql Server 2005 database (or you want to treat the database as if it was Sql Server 2005), “2008” indicates you are connecting to the Sql Server 2008 database etc. The store model can look differently depending on the provider manifest token – the simplest example is the date time type – if you have properties of DateTime type in your conceptual model then the properties in your store model will be of datetime type if the provider manifest token is “2005” but it will be datetime2 if the provider manifest token is “2008” (datetime2 was introduced in Sql Server 2008)) and to obtain the provider manifest token EF connects to the database and read it using from the properties of the connection. Note that EF does not have to connect to a specific database – “master” database is good enough to read the properties. In EF6 we introduced a dependency resolver which contains a provider manifest token service that can be implemented in a way that does not require connecting to the database (e.g. if you know that you will always connect to Sql Server 2008 you can just hard code and return the value) and therefore it should be possible to generate views without having to connect to the database.

        Like

Leave a comment