Looking at EF4 CTP5 in Parts: Part 4–Working with New and Existing Databases in Code First

One of the neat features of Code First  in CTP5 for those who are starting from total scratch…no database at all.. is that there is default behavior for working with a database. You don’t even need a database connection string. If you do not specify a connection string anywhere …code or config…then Code First will make a presumption about the database.  THe default presumption is that the database is the same name as your context class and is a local SQL Server Express instance.

Here’s an example.

I’ve got a context class called AWEntities.

namespace CTP5_Modeling
{

  public partial class AWEntities : DbContext
  {
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Detail> Details { get; set; }
    public DbSet<Order> Orders { get; set; }
  }
}

When I instantiate that class:

var context = new AWEntities();

You can see, in this debugger screenshot of the context, the database connection string that is created when there is no other available:

defaultdatabase

 

It presumes the database has the name of the class’ namespace plus name, CTP5_Modeling.AWEntities and that it’s SQL Express.

If the database doesn’t already exist, it will create it for you.

dbcreated

And by default, any time you instantiate the context again, it will check to be sure that your code first classes still line up with the schema of that database.

If not, you’ll get an error like this:

modelchanged

Now what if you want your code first classes to work with an existing database.

Step #1, you’ll need your database connection string, of course. Not an EntityConnection  string, but a regular database connection string.

Just to be clear, here is a typical EntityConnection String:

<add name="AWEntities"
           connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;
                                                  provider=System.Data.SqlClient;
                                                  provider connection string=&quot;Data Source=.;Initial Catalog=AdventureWorksSuperLT;
                                                                                                                         Integrated Security=True;MultipleActiveResultSets=True&quot;"
                                                  providerName="System.Data.EntityClient" />

With code first, there is no metadata and with not metatadata you won’t need the EntityClient provider.

Here is the connection string  that I’m using for the SQL Server instance of my database:

<add name="AWEntities"
            connectionString="Data Source=.;Initial Catalog=AdventureWorksSuperLT;
                                                    Integrated Security=True;MultipleActiveResultSets=True"
            providerName="System.Data.SqlClient"/>

There’s still one problem. The presumptions that code first will make at runtime about my database (based on my classes) don’t exactly match my database.

For example, I have a Customer class. Code first will presume that the database table has the same name as the EntitySet. The EntitySet will be specified on the fly at runtime by code first as the plural of the class name, e.g., Customers. However my database table name is customers.

I can fix that up with attributes from the using System.ComponentModel.DataAnnotations namespace:

[Table("Customer", SchemaName="SalesLT")]
public partial class Customer
{
}

Notice also that I’m specifying the schema. Otherwise it will default at dbo and my store query will fail when it tries to query against dbo.Customer.

Also, I have simplified names of some classes and some properties.

In the database, there is a table called SalesOrderHeader with a primary key field called SalesOrderID.

The relevant class is called Order with a key field of OrderID. Code first will look for a table called Orders with a SalesOrderID primary key field. SO I have to use attributes to instruct code first.

Here’s a bit of that class with the relevant attributes:

[Table("SalesOrderHeader", SchemaName="SalesLT")]
public partial class Order
{

   [Column(Name="SalesOrderID")]
   public int OrderId { get; set; }

Whether you want CTP5 code first have total ownership of the database or you want it to use your existing database, this should get you started with leveraging the new bits.

Leave a Reply

Your email address will not be published. Required fields are marked *