Don’t use Code First by mistake

EF Code First is great and I use it all the time, even when mapping to existing databases. However, if your intention is to use a Database First flow, then it’s important that you don’t start to use Code First unintentionally. If you do, then you might end up with exceptions like those described in this Stack Overflow question.

Code First can be used both when you want the database to be created from your entity classes and when mapping your entity classes to an existing database. But EF also supports another way of mapping an existing database to an object model—this is usually referred to as the Database First approach or workflow. The EF designer in Visual Studio takes this approach when the new Entity Data Model wizard is used and “Generate from database” is chosen. There is a walkthrough for this on the EF team blog for EF 4.2—the same walkthrough can also be used for EF 4.3.

How Database First works

These two approaches differ fundamentally in the way DbContext behaves when the application is run. With the Database First approach an EDMX file is created by the EF Designer and (usually) embedded in the application assembly. This EDMX file contains all the information required to map between the entity classes and the database. For example, if one of the entity classes is called “User” but the corresponding table in the database is called “t_userdata”, then this mapping is included in the EDMX file. Such mapping is usually configured using the EF Designer but can also be added through editing the XML in the EDMX file directly.

When a Database First application is run the DbContext must load this EDMX file so that it knows how to map between entity classes and the database. This is done through a special EF connection string which is created for you and added to your config file by the EF Designer. The connection string will look something like this:

<connectionStrings>
  <add name="MyEntities"
  connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;
    provider=System.Data.SqlClient;provider connection string=&quot;
    datasource=.\sqlexpress;initial catalog=MyEntities;
    integrated security=True;multipleactiveresultsets=True;
    App=EntityFramework&quot;"
  providerName="System.Data.EntityClient" />
</connectionStrings>

Notice that this connection string contains references to “CSDL”, “MSL”, and “SSDL” metadata. This is the contents of the EDMX that has been embedded in the application assembly.

How Code First works

With the Code First approach there is no EDMX file. There is nothing in the VS project that contains the mapping information from entity classes to database…except for the code itself.

When a Code First application is run the DbContext constructs the mapping to the database the first time that the context is used. It does this through a combination of convention, configuration by data annotations, and configuration using the Code First DbModelBuilder fluent API. Taking the example above again, by convention Code First will map the User class to a table called “Users” in the database. If the table is instead called “t_userdata” then this must be specified either using the Table data annotation or through a call to the ToTable method.

How it can go wrong

Imagine you are using the Database First approach and have an EDMX containing all your mapping information. Now consider what happens if you run your application and it fails to find this EDMX but instead uses Code First to create mappings by convention. There won’t be anything in your code to map the User class to the t_userdata table. So the model created by Code First will assume that the table is called “User” and will attempt (but fail) to run queries against that table.

How to prevent it going wrong

When you use the Database First approach with the DbContext T4 templates two things are setup to protect against things going wrong in this way.

First, the generated context class makes a call to the base DbContext constructor specifying the name of this connection string. For example:

public MyEntities()
: base("name=MyEntities")
{
}

This tells DbContext to find and use the "MyEntities" connection string in the config—i.e. the one created by the designer as described above.

Using "name=" means that DbContext will throw if it doesn’t find the connection string—it won’t just go ahead and create a connection by convention. Be very careful if you change this call to the base constructor. Make sure that whatever change you make DbContext is still able to find the correct connection string containing the information from your EDMX. If DbContext finds a non-EF connection string or creates a connection string by convention then it will start using Code First to create a model for that connection.

The second thing that happens is that the OnModelCreating is overridden in the generated context and made to throw:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    throw new UnintentionalCodeFirstException();
}

To see why this happens consider how OnModelCreating is used; OnModelCreating is a way of making calls to the Code First DbModelBuilder fluent API. In other words, it’s a way of setting up Code First mappings. This means that OnModelCreating will never be called when using the Database First approach. It will never be called because all the mappings already exist in the EDMX and so Code First and the DbModelBuilder are never used.

The message from the exception reads:

Code generated using the T4 templates for Database First and Model First development may not work correctly if used in Code First mode. To continue using Database First or Model First ensure that the Entity Framework connection string is specified in the config file of executing application. To use these classes, that were generated from Database First or Model First, with Code First add any additional configuration using attributes or the DbModelBuilder API and then remove the code that throws this exception.

This is message is an attempt to distil the contents of this post into an exception message. A hard job!

But what if I intended to use Code First?

Now, it might be that you want to use Code First to map to an existing database. As I stated at the top of this post, using Code First in this way is a great pattern and fully supported. However, you will need to make sure mappings are setup appropriately for this to work. Don’t just delete the code that throws this exception and expect things to work. You’ll also need to make sure that you setup any mappings to the database correctly, using data annotations and/or the fluent API.

Thanks,
Arthur

About Arthur Vickers

Developer on the Entity Framework team at Microsoft.
This entry was posted in Code First, Database First, DbContext API, Entity Framework and tagged , , , , , , , , . Bookmark the permalink.

37 Responses to Don’t use Code First by mistake

  1. Arthur, EF Power Tools has “Reverse Engineer Code First”, do you intend to continue to support this tool? It´s been 1 year without updates and a RTM version.
    Thanks

    • @Felipe The short answer is yes. The longer answer is that the PowerTools were a small side project of a couple of guys on the team. We’ve been focusing on 4.3 and 5.0 as a priority, but there is now somebody working on the updating the PowerTools to take advantage of 4.3 and 5.0 features. We should be able to get an update out relatively soon. That being said, the T4 templates to create Code First mappings are not being updated extensively as part of the next refresh–they will be included, but not updated a lot. However, we do intend to move these forward and add some additional functionality to them, but it’s not yet clear what the priority of this work will be.

  2. Verogo says:

    Hello, I have a question. I need to use two different databases,both of them have different structure. could I use two different dbcontexts?. I have looked for this kind of information but I don’t find anything!

  3. Programmer says:

    I hate the Code first from MVC4 SPA project template! How should change it to use EF?!

    • Programmer: Sorry, but I don’t understand your question.

      • Programmer says:

        There is a project template in Visual Studio called Single Page Application and it uses Code first approach for TodoItemContext and UserContext entities. I would like to have this in a DB first approach…

      • I’m curious why you want to use Database First for this, but if you do, then you will need the appropriate databases, so either use Code First to create them or create them manually. After that, just use the EF designer to create the Database First contexts and delete the ones scaffolded for you.

  4. Mohsen says:

    Hi Arthur,
    I have a web project with a ‘database first’ EF model. After passing unit tests and the web application integration tests using my local SQL server, I published the database to SQL Azure and web application to Windows Azure. Then I started getting:
    “Code generated using the T4 templates for Database First and Model First development may not work correctly if used in Code First mode. To continue using Database First or Model First ensure that the Entity Framework connection string is specified in the config file of executing application. To use these classes, that were generated from Database First or Model First, with Code First add any additional configuration using attributes or the DbModelBuilder API and then remove the code that throws this exception.”
    I changed the app config in my unit test project to point to SQL azure and it passed. Then I changed my local web.config to point to SQL azure and it also worked. Then I published the web project to Windows Azure and again the same problem.
    Any help is really appreciated.
    Mohsen

    • Hi Mohsen,

      The reason you get this exception is, as you seem to have figured out, that Code First is not finding your connection string, or the connection string is a “normal” connection string rather than an EF connection string containing metadata. I can’t tell from the info you provided why this is–I would suggest some debugging to figure out which config file is being used.

      It’s also worth noting that SQL Azure behaves differently than local SQL Server in quite a number of ways, so if you intend to use SQL Azure in production then you definitely need to test against SQL Azure.

      Thanks,
      Arthur

  5. Jega says:

    Hi Arthur,

    I am stumbling with this issue for a while and now i understand why i am getting the error ““Code generated using the T4 templates for Database First and Model First development may not work correctly if used in Code First mode. To continue using Database First or Model First ensure that the Entity Framework connection string is specified in the config file of executing application. To use these classes, that were generated from Database First or Model First, with Code First add any additional configuration using attributes or the DbModelBuilder API and then remove the code that throws this exception.”

    The issue i am facing currently is EF based business logic is called from a legacy application which doesn’t support config files. Since the original call is initiated form the legacy i am unable to add the config. file to include the Entity informations.

    Is there a way to specify the connection string programmatically in DB First approach.
    Your help is greatly appreciated.

    —————————————————————————————–
    Trying to figure out a way to add a connection string. I added the following code to the constructor of the Entity class.. When running this implementation i get this error :

    Message = “Keyword not supported: ‘metadata’.”

    If i remove the MetaData from the connection string then i get this error :

    Code generated using the T4 templates for Database First and Model First development may not work correctly if used in Code First mode. To continue using Database First or Model First ensure that the Entity Framework connection string is specified in the config file of executing application. To use these classes, that were generated from Database First or Model First, with Code First add any additional configuration using attributes or the DbModelBuilder API and then remove the code that throws this exception.

    public partial class TestQEntities : DbContext
    {

    public TestQEntities(string nameOrConnectionString)
    {
    this.Database.Connection.ConnectionString = nameOrConnectionString;
    }

    }

    }

    _context = new TestQEntities(GetConnectionString());

    private static string GetConnectionString()
    {
    var scsb = new SqlConnectionStringBuilder
    {
    DataSource = “(local)”,
    InitialCatalog = “DB”,
    IntegratedSecurity = true
    };

    var builder = new EntityConnectionStringBuilder
    {
    Metadata = “res://*/ROModel.csdl|res://*/ROModel.ssdl|res://*/ROModel.msl”,
    Provider = “System.Data.SqlClient”,
    ProviderConnectionString = scsb.ConnectionString
    };
    return builder.ToString() + “;App=EntityFramework”;
    }
    }

  6. Jega says:

    Hi Arthur,

    Now i understand the issue i am stumbling upon for quite some time. Thanks for the great explaination.

    I have a EF Model generated from a existing database.

    BL using the EF model is called from a legacy application which doesn’t have a configuration file and i couldn’t add the EF Entity connection string.

    Trying to figure out a way to add a connection string. I added the following code to the constructor of the Entity class.. When running this implementation i get this error :
    Message = “Keyword not supported: ‘metadata’.”

    If i remove the MetaData from the connection string then i get this error :
    Code generated using the T4 templates for Database First and Model First development may not work correctly if used in Code First mode. To continue using Database First or Model First ensure that the Entity Framework connection string is specified in the config file of executing application. To use these classes, that were generated from Database First or Model First, with Code First add any additional configuration using attributes or the DbModelBuilder API and then remove the code that throws this exception.

    Code:

    public partial class TestQEntities : DbContext
    {

    public TestQEntities(string nameOrConnectionString)
    {
    this.Database.Connection.ConnectionString = nameOrConnectionString;
    }

    }

    Your help is greatly appreciated.

    _context = new TestQEntities(GetConnectionString());

    private static string GetConnectionString()
    {
    var scsb = new SqlConnectionStringBuilder
    {
    DataSource = “(local)”,
    InitialCatalog = “DB”,
    IntegratedSecurity = true
    };

    var builder = new EntityConnectionStringBuilder
    {
    Metadata = `enter code here`”res://*/ROModel.csdl|res://*/ROModel.ssdl|res://*/ROModel.msl”,
    Provider = “System.Data.SqlClient”,
    ProviderConnectionString = scsb.ConnectionString
    };
    return builder.ToString() + “;App=EntityFramework”;
    }

  7. @Jega You should be able to pass an EF connection string to the DbContext constructor. You can’t set an EF connection string onto the Database.Connection property because this is the actual database connection, rather than an EF connection with metadata information.

    Also, even when using normal connections it is still recommended that you pass the connection string to the DbContext constructor and not try to set it on the Database.Connection object because EF has to initialize the Connection object in order for you to set the connection string onto it and this initialization may happen differently depending on the type of connection that will ultimately be used.

  8. Akila Kumarasamy says:

    Good reading. This is very true for the beginners who uses EF and by mistake using one for the other. Thank you very much for the post. This gave me a clear understand of what mistake I did.

  9. Great article!! made me start to understand how things actually work in the MVC universe and CF/ DbF!!

  10. Martin says:

    Hi Arthur, thanks, this was really clarifying, not much of these quality info about EF around the web. I’m struggling to include Effort test layer in my EF Database-First application, but it keeps interpreting as CodeFirst (entering to ‘OnModelCreating’ method).

    After reading your article, I assume this happens becouse EFFORT creates a new connectionstring to their own datasource, and this does not include metadata info.

    Do you have any experience with EFFORT? Or do you recommend another pattern or tool for testing using the EF model?

    Thanks!
    Martin

    • @Martin

      I don’t have any knowledge of EFFORT, so I won’t comment on that. With regard to testing, there really is a huge spectrum. Rowan Miller wrote a good post on using test doubles, which I think is a good place to start for unit testing. With regard to more functional/end-to-end testing, we haven’t really had any problems just using SQL Express (or localdb if you must) is not a bad option. It’s actually fast enough to run lots of tests quickly as long as the database creation/deletion is kept under control.

      Thanks,
      Arthur

  11. Anson says:

    Hi Arthur,

    I just would like to know Is the EF Team going to implement the Data Annotation(D.A.) for Db First?
    I know there is a workaround like creating a partial class for each entity to implement the D.A. but I think it isn’t a good way for Db First approach. Or I should choose Code First instead?

    Please advice. Thanks.

    Anson

    • @Anson We’re not planning to do this anytime soon. It’s a difficult area in terms of usability because adding data annotations on an entity used with an EDMX will not cause the model as defined in the EDMX to change. So for example, someone may think that adding a Key attribute will make the property a key, but it won’t. It is in our plans to improve reverse engineering to Code First and hopefully this can include reverse engineering to data annotations as well as the fluent API. This would be a much more understandable experience.

      Thanks,
      Arthur

  12. Brian Watt says:

    Thanks for the article it got me sorted out with some confusion about the metadata portion of the connection string.

    As an aside, how is EF getting that connection string? I had code to inject my own ConfigurationManager implementation, but EF never triggered a call to GetSection. Both,

    ConfigurationManager.ConnectionStrings(“DB1″)
    ConfigurationSettings.GetConfig(“connectionStrings”)

    caused my implementation to be called. I was trying to use this to determine connection strings at runtime. I ended up going with adding an additional constructor to the automatically generated entities class.

    • @Brian Watt: It looks like EF uses “ConfigurationManager.ConnectionStrings[namedConnection];” to get a named connection string. I’m not sure how you are injecting your configuration manager or why it isn’t working for you. EF doesn’t seem to be doing anything special.

      • Brian Watt says:

        I haven’t had time to dig down and find out why my code didn’t get called. The only thing I could think of was that EF was getting access to the config file before I called IInternalConfigSettingsFactory.SetConfigurationSystem – which I was doing in Application.OnStartup.

        I switched to the alternate constructor method I mentioned in response to Nicole’s comment and have had to let sleeping dogs lie on this issue.

  13. Nicole says:

    Great article!!!
    I have one issue I am trying to resolve for days now, but I can’t get the right approach.
    I am using EF4 and I have one application where I use DataBase First, which originally created the ObjectContext, and I donwloaded the DbContext generator and generated it.
    The thing is, I need the application to be able to get the database SCHEMA from some configuration file, instead of ALWAYS using the “dbo” default.
    I was trying to use the “ToTable” method (so I can specify the schema) in the “OnModelCreating” overload method but as you say, as I am using DataBase First, that method is not called.
    How can I make the schema name configurable?
    Is that even possible?
    I read this (http://blogs.msdn.com/b/adonet/archive/2011/03/07/when-is-code-first-not-code-first.aspx) article too, whare it says I can combine database first with code first but I can’t see how to do that if I can’t use the OnModelCreating method.

    Thanks a lot in advance!!!

    • @Nicole It seems that you have two choices. First, stay with Database First, but then modify the metadata dynamically at runtime before the context is created. This article is a bit old but it covers the idea: http://blogs.msdn.com/b/alexj/archive/2009/11/29/tip-45-how-to-swap-ef-metadata-at-runtime.aspx

      Second, move to Code First and don’t use the EDMX at all. You’ll need to setup your Code First mappings to match those that were previously specified in the EDMX. The Power Tools can help with this, but it will probably require some manual tweaks depending on how much the model differs from a straight one-to-one mapping from the database. Once you have Code First mappings you should be able to change the schema, although if you are using EF5 or earlier you will likely have to handle model caching yourself. EF6 has built-in support for changing the default schema.

      Thanks,
      Arthur

    • Brian Watt says:

      Another possibility: provide an alternate constructor. Since the generated entities class is a partial, you can provide another constructor that implements your configuration logic and passes a connection string (without name= in front of it) to the EF-generated constructor.

      Without the name= at the front of the connection string, EF will use the string provided as a raw connection string if it can’t find a matching setting in app.config. I used this so I could have a centralized database to provide configuration setting for different environments (DEV, QA, UAT, PROD) for all of our applications.

  14. jay lalwani says:

    which is the best approach code first or database first ?

  15. jay lalwani says:

    As i am new to EF, i will really appreciate any comments on which is the best approach code first or database first ?. Thanks.

    • Personally I would always use Code First because I find code easier to work with than a design surface backed by XML artifacts. However, different people have different preferences. There is a lot of good information at the main EF documentation site to help you decide: http://msdn.com/data/ef

      Thanks,
      Arthur

  16. Zaineb says:

    I am creating a Database with the Model First SQL Script Generation. Then later when I need to Update the Model I don’t want to delete all tables and content, I want to generate an update Script.

    Its possible in EF4 with an Tool:

    http://visualstudiogallery.msdn.microsoft.com/df3541c3-d833-4b65-b942-989e7ec74c87/

    but in EF5 there is atm no possibility to update the Model with “Model first”.

  17. James says:

    Hi Arthur, is it possible to combine Code + Database First approaches in a single app and single DbContext? For instance, the app would use CF for describing the table to entity mapping, and use DbF T4 code gen for mapping stored procs and user defined funcs. This would give you best of both worlds (i.e. using CF for migrations and DbF for generating stored proc and UDF proxies).

    • @James Any given context can be either a Code First context or use EDMX, but not both. You could have different contexts in an app some of which that use Code First and some of which use EDMX, but I don’t think that’s what you are asking.

  18. Larry Shewell says:

    I have a need to be able to dynamically change the table name that an entity is mapped to. I was encouraged when I found the OnModelCreating() method and the Fluent API. But then after further research (and this article) I realized that this method can only be used with the code-first approach. Is there a way to update the entity mapping metadata when using the model-first approach?

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