EF Feature CTP4: DbContext & Databases
We recently announced the release of Feature CTP4 for the ADO.Net Entity Framework (EF). CTP4 contains a preview of new features that we are considering adding to the core framework and would like community feedback on. CTP4 builds on top of the existing Entity Framework 4 (EF4) which shipped as part of .NET Framework 4.0 and Visual Studio 2010.
CTP4 contains the first preview of a set of Productivity Improvements for EF that provide a cleaner and simpler API surface designed to allow developers to accomplish the same tasks with less code and fewer concepts. The Productivity Improvement effort is described in more detail in a recent Design Blog post.
In addition to a simplified API surface the Productivity Improvements also offer a streamlined Code First experience that takes care of common boiler plate code and uses convention over configuration to reduce the amount of code needed to start performing data access. You can then gradually start to override these conventions with your own configuration as you progress through the development lifecycle and ultimately deploy to a production environment. One example of these conventions is database location and provisioning which we will cover in this post.
This post is largely targeted at using the Code First approach with DbContext to generate a database, if you are mapping to an existing database then this is covered at the end of the post.
Default ConventionsFirst let’s look at the default behavior of DbContext and how it uses convention rather than configuration to reduce the amount of code we need to write to get an application up and running. Below is a complete application that uses DbContext to persist and query data using DbContext. No additional code or configuration is required; DbContext will automatically create a database for us based on our domain model. The database will be created on our localhost\SQLEXPRESS instance and will be named after the fully qualified type name of our derived context (in the following example this would be PI.DbDemo.ProductCatalog).
using System;
using System.Collections.Generic;
using System.Data.Entity;
namespace PI.DbDemo
{
class Program
{
static void Main(string[] args)
{
using (var context = new ProductCatalog())
{
// Persist Data
var food = new Category { Name = "Food" };
context.Categories.Add(food);
context.SaveChanges();
// Query Data
foreach (var cat in context.Categories)
{
System.Console.WriteLine(cat.Name);
}
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
public class ProductCatalog : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public ICollection Products { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public decimal UnitPrice { get; set; }
public Category Category { get; set; }
}
}
Of course this convention is useful to get up and running but it’s not going to get us all the way to deploying in a production environment, you probably aren’t going to be using a local SQL Express instance in production and if you’re an enterprise developer your DBA probably isn’t going to overjoyed at the idea of you application having permissions to create databases (with good reason). In the next sections we’ll look at how you can start to take control over the database as your requirements progress.
Connection FactoriesUnder the covers there is a convention that is taking the name of your context and turning it into a database connection, this is an AppDomain wide setting that can be changed via a static property; System.Data.Entity.Infrastructure.Database.DefaultConnectionFactory. Connection factories implement the System.Data.Entity.Infrastructure.IDbConnectionFactory interface which defines a single CreateConnection method. When you use the default constructor on DbContext the fully qualified name of your context is passed to the default connection factory to obtain a database connection.
public interface IDbConnectionFactory
{
DbConnection CreateConnection(string nameOrConnectionString);
}
Changing the Database Name
If you just want to change the name of the database that is generated then you can control the string that is passed to the default connection factory by using the DbContext constructor that specifies the nameOrConnectionString parameter. Here is our derived context updated to specify a database name:
public class ProductCatalog : DbContext
{
public ProductCatalog()
:base("DemoProductStore")
{ }
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
Changing the Database Server
If you want to have your database on another Microsoft SQL Server Instance then you can tweak the settings on the SQL Client connection factory that is included in CTP4; System.Data.Entity.Infrastructure.SqlConnectionFactory. This connection factory includes a constructor that allows us to override pieces of the final connection sting, such as username, password and server. We need to make changes to the default convention before any contexts are created in our AppDomain, in the case of our console application we can just do this at the start of the Main method:
static void Main(string[] args)
{
Database.DefaultConnectionFactory =
new SqlConnectionFactory("Server=MyDatabaseServer");
...
}
Changing to SQL Compact
Along with the SQL Client connection factory we also include the System.Data.Entity.Infrastructure.SqlCeConnectionFactory which will generate connections to SQL Compact databases. Because the SQL Compact providers aren’t backwards compatible you will need to specify the invariant name of the provider version you want to use. Currently the SQL Compact 4.0 provider is the only one that supports Code First database creation and it is available for download as a separate CTP.
static void Main(string[] args)
{
Database.DefaultConnectionFactory =
new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
...
}
By default SQL Compact files will be created in the |DataDirectory| directory, for executables this is the same directory as the executable, for web applications this is the ‘App_Data’ directory. The SQL Compact factory also includes constructors to override the directory that databases are created in, or any other part of the connection string.
App.config/Web.configAll these conventions are great but if our database server changes between dev, test and production then we really want to be able to change it easily without having to recompile code. No problem, just add a connection string to your applications config file with a name that matches the name of your context (either fully-qualified or not). Because the shape of the model comes from your code rather than xml files this is just a plain connection string rather than an EntityClient connection string used in other areas of EF.
<configuration>
<connectionStrings>
<add name ="ProductCatalog"
providerName="System.Data.SqlClient"
connectionString="Server=.\SQLEXPRESS;Database=ProductCatalog;Integrated Security=True" />
</connectionStrings>
</configuration>
Note that if you pass a string to a DbContext constructor (for the nameOrConnectionString parameter) then that string should match the name of the connection string added to your config file.
Database InitializersSo far we’ve looked at how a database is located, now let’s look at how that database is initialized. By default if the database does not exist then DbContext will automatically create a database for you without any data in it, but of course this can be changed. Database initialization is handled via a setting at the AppDomain level which can be tweaked or replaced for your context via the static System.Data.Entity.Infrastructure.Database.SetInitializer method. Initializers need to implement the System.Data.Entity.Infrastructure.IDatabaseInitializer interface, which contains a single method to initialize the database for a given context:
public interface IDatabaseInitializer<in TContext>
where TContext : DbContext
{
void InitializeDatabase(TContext context);
}
Having this very-generalized hook gives developers and third parties the opportunity to build custom solutions to help with initialization, in addition to the options provided in the box.
It is worth calling out that this is a very new feature that only just made it into CTP4 and we know it has some rough edges, but we really want your feedback so we decided to include it. As you’ll see when we look at evolving models there are some missing pieces in the CTP4 story but we feel like the database initializer hook is the right way to approach the problem and we just need to expand the abilities of the initializers and tooling that we provide.
Evolving ModelsOf course it is unlikely that our domain model will remain the same forevermore after the first time we run our application. This in turn means our database schema is going to need to evolve along with our domain model, this scenario is going to highlight one of the big gaps in CTP4 and something we are working to improve. Ideally we would have a set of tools that help you migrate the existing database, either automatically or by generating migration scripts that can be tweaked and then saved for later use against test and production databases. We’re not there yet though, in CTP4 you need to drop and re-create the database with the new schema to match your domain model.
So let’s go ahead and change our domain model, I’m just adding a Description field to our Product class:
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public decimal UnitPrice { get; set; }
public string Description { get; set; }
public Category Category { get; set; }
}
Now if we run our application we’ll get an InvalidOperationException because our schema doesn’t have a column for the new Description field:
“The model backing the 'ProductCatalog' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the RecreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.”
As the exception suggests there is an initialization strategy in CTP4 that will drop and re-create the database for us when the model changes. We need to register the initializer before any contexts are created in our AppDomain, in the case of our console application we can just do this at the start of the Main method. Running the application again will cause the old database to be dropped and the new database with the Description column to be created, obviously this isn’t ideal for all situations but it’s where we got to for CTP4.
static void Main(string[] args)
{
Database.SetInitializer<ProductCatalog>(
new RecreateDatabaseIfModelChanges<ProductCatalog>());
....
}
Other Strategies
In addition to the RecreateDatabaseIfModelChanges strategy CTP4 also includes two other strategies, CreateDatabaseOnlyIfNotExists and AlwaysRecreateDatabase, the names are pretty self-explanatory. CreateDatabaseOnlyIfNotExists is the default strategy. AlwaysRecreateDatabase can be useful in testing when combined with seed data, allowing you to reset the database to a clean state before each test run, this is shown in the next section.
Seed DataAll three of the strategies included in CTP4 can be derived from and have a virtual Seed method that is called after the database has been created. This allows us to insert some data into the database once it has been created, an instance of the context type is passed into the method so you can specify seed data in terms of your domain objects and use the context to persist them. Of course the underlying database connection is available from context.Database.Connection so you can always interact directly with the database if you want.
Let’s define an initializer for use in a test project that will recreate the database before each test run with a known set of test data. I’m sure some of you are cringing at the thought of running tests against an actual database all the time. It’s definitely not for everyone and you can certainly use interfaces and in-memory fakes rather than hitting the database (we created the IDbSet<T> interface for exactly this reason). This is simply another option for folks who don’t need/want to create a layer of abstraction between their application and data access layer.
public class ProductTestInitializer : AlwaysRecreateDatabase<ProductCatalog>
{
protected override void Seed(ProductCatalog context)
{
var food = new Category { Name = "Food" };
context.Categories.Add(food);
context.Products.Add(new Product
{
Name = "Bread",
UnitPrice = 2,
Category = food
});
context.Products.Add(new Product
{
Name = "Butter",
UnitPrice = 5,
Category = food
});
context.Products.Add(new Product
{
Name = "Vegemite",
UnitPrice = 4,
Category = food
});
}
}
If we are using MSTest (included with Visual Studio) for our testing then we use a ‘Class Initialize’ method to register the initializer, this will run before we construct a context in any of our tests:
[TestClass]
public class MyTests
{
[ClassInitialize]
public void ClassInitialize(TestContext c)
{
Database.SetInitializer<ProductCatalog>(new ProductTestInitializer());
}
[TestMethod]
public void MyTest1()
{
}
}
Schema Metadata
One of the challenges in database initialization is in knowing whether an existing database is compatible with the current domain model. In CTP4 we include an additional “EdmMetadata” table in generated schemas to help answer this question. The table includes some information about the model that was used to generate the database and is used internally to support the DbContext.Database.ModelMatchesDatabase method.
Of course not everyone is going to be happy with this table being included in their database so you can switch it off using the Code First ModelBuilder API, if you do turn it off then some of the initialization strategies will not be able to function correctly.
public class ProductCatalog : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.IncludeMetadataInDatabase = false;
}
}
Customizing the Generated Schema
Not everyone is going to be happy with the database schema that is generated by default. It’s not really in the scope of this post but we’ll take a quick look at customizing the schema. Below is an example of using the Fluent API to control the table names for our two classes. The Fluent API provides many more knobs for controlling the schema including column names, splitting entities between multiple tables, inheritance patterns and many more. This is one area of the Fluent API that still has some rough edges and we are working to make the code required for mapping more succinct and intuitive for the next release.
public class ProductCatalog : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Category>()
.MapSingleType()
.ToTable("purchasing.CategoryLookup");
modelBuilder.Entity<Product>()
.MapSingleType()
.ToTable("purchasing.ProductCatalog");
}
}
Working with Existing Databases
Most of the content in this post has dealt with scenarios where Code First is responsible for generating the database. If you have an existing database then you don’t need database location or initialization. Here is the process to follow for using Code First against an existing database:
- Define the classes that make up you domain model
- Define a derived DbContext and use the Fluent API and/or DataAnnotations to tell Code First how your classes map to your database
- Add a connection string to you app/web.config file that has the same name as your derived context and points to your database
- Switch off the initialization functionality for your context by registering null:
Database.SetInitializer<ProductCatalog>(null);
In this post we looked at how DbContext locates a database and initializes it for Code First developers. We covered the default behavior and how to tweak it or replace it with your own behavior, we also saw how to turn off the conventions when mapping to an existing database. There are some missing pieces in the database initialization space but we would like your feedback on the hooks we have made available and the general approach we are taking.
If you need assistance with EF Feature CTP4 we have an Entity Framework Pre-Release Forum.
Rowan Miller
Program Manager
ADO.Net Entity Framework
Performance Considerations when using TPT (Table per Type) Inheritance in the Entity Framework
The Entity Framework offers very rich inheritance mapping schemes for building your conceptual model. The inheritance capabilities in EF include:
· TPH (Table per Hierarchy): This is the inheritance scheme where there is a single table in the database representing the hierarchy, but the conceptual model includes multiple entities.
· TPT (Table per Type): In this scheme, each type in the inheritance hierarchy is stored in separate tables in the database
· TPC (Table per Concrete type): In this scheme, each concrete type in the inheritance hierarchy is stored as a separate database table, without any tables in the database for the abstract types. TPC is currently not supported by the Entity Designer in Visual Studio.
All of these inheritance schemes have their own strengths and weaknesses. One thing in particular to consider is that queries done on entities in a TPC or TPT mapped hierarchy are naturally more complicated to represent and translate to the store because of the fact that multiple tables may be involved, which usually require joins or unions. This can introduce performance problems that stem from the complexity of queries generated by EF. On the other hand, TPH fares relatively well when it comes to query complexity.
Take an example of a simple TPT inheritance hierarchy, as shown below:

Now, let’s take an example of a rather simple query that projects some properties out of the base type Guest, without ever querying for anything from any of the subtypes.
var query = from g in db.Guests
select new { Id = g.GuestId, Name = g.Name };
This results in a query that is shown below. This scenario really should only generate a query that involves the base Guests table – however, EF generates a query that includes a join over the union of two of the tables for the sub-types as well.
SELECT
[Extent1].[GuestId] AS [GuestId],
[Extent1].[Name] AS [Name]
FROM [dbo].[Guests] AS [Extent1]
LEFT OUTER JOIN (SELECT
[Extent2].[GuestId] AS [GuestId]
FROM [dbo].[Guests_USGuest] AS [Extent2]
UNION ALL
SELECT
[Extent3].[GuestId] AS [GuestId]
FROM [dbo].[Guests_UKGuest] AS [Extent3]) AS [UnionAll1] ON [Extent1]
.[GuestId] = [UnionAll1].[GuestId]
Here’s another example.
var query = db.Guests;
This LINQ query seems even more simple than the previous one – but the resulting query is not as simple as you might expect, because what we are effectively doing is requesting a polymorphic result set that includes multiple types.
The scenario itself is naturally more complicated than it seems – however EF is doing extra work to ensure that when returning flattened table that includes the data for all the types, that null values are returned for columns that may be irrelevant for a particular type. Technically, this extra validation is not necessary and the highlighted parts of the query can be safely ommitted from the SQL we generate.
SELECT
CASE WHEN (( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL))) AND ( NOT (([UnionAll1].[C4] = 1) AND ([UnionAll1].[C4] IS NOT NULL)))) THEN '0X' WHEN (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)) THEN '0X0X' ELSE '0X1X' END AS [C1],
[Extent1].[GuestId] AS [GuestId],
[Extent1].[Name] AS [Name],
[Extent1].[Address] AS [Address],
[Extent1].[City] AS [City],
CASE WHEN (( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL))) AND ( NOT (([UnionAll1].[C4] = 1) AND ([UnionAll1].[C4] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)) THEN [UnionAll1].[State] END AS [C2],
CASE WHEN (( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL))) AND ( NOT (([UnionAll1].[C4] = 1) AND ([UnionAll1].[C4] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)) THEN [UnionAll1].[Zip] END AS [C3],
CASE WHEN (( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL))) AND ( NOT (([UnionAll1].[C4] = 1) AND ([UnionAll1].[C4] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)) THEN [UnionAll1].[PhoneNumber] END AS [C4],
CASE WHEN (( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL))) AND ( NOT (([UnionAll1].[C4] = 1) AND ([UnionAll1].[C4] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) ELSE [UnionAll1].[C1] END AS [C5],
CASE WHEN (( NOT (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL))) AND ( NOT (([UnionAll1].[C4] = 1) AND ([UnionAll1].[C4] IS NOT NULL)))) THEN CAST(NULL AS varchar(1)) WHEN (([UnionAll1].[C3] = 1) AND ([UnionAll1].[C3] IS NOT NULL)) THEN CAST(NULL AS varchar(1)) ELSE [UnionAll1].[C2] END AS [C6]
FROM [dbo].[Guests] AS [Extent1]
LEFT OUTER JOIN (SELECT
[Extent2].[GuestId] AS [GuestId],
[Extent2].[State] AS [State],
[Extent2].[Zip] AS [Zip],
[Extent2].[PhoneNumber] AS [PhoneNumber],
CAST(NULL AS varchar(1)) AS [C1],
CAST(NULL AS varchar(1)) AS [C2],
cast(1 as bit) AS [C3],
cast(0 as bit) AS [C4]
FROM [dbo].[Guests_USGuest] AS [Extent2]
UNION ALL
SELECT
[Extent3].[GuestId] AS [GuestId],
CAST(NULL AS varchar(1)) AS [C1],
CAST(NULL AS varchar(1)) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
[Extent3].[PostalCode] AS [PostalCode],
[Extent3].[PhoneNumber] AS [PhoneNumber],
cast(0 as bit) AS [C4],
cast(1 as bit) AS [C5]
FROM [dbo].[Guests_UKGuest] AS [Extent3]) AS [UnionAll1] ON [Extent1].[GuestId] = [UnionAll1].[GuestId]
These are two very common cases that you may have run into when using TPT with the Entity Framework. The good news is that we are working on these issues so that EF no longer generates unnecessary SQL. The bad news is that it will take some time before the fix is delivered in a future release.
So, until we are able to get these fixes in place, there are a few things you can do to make sure you don’t get affected by some of these issues:
Pay special attention when using Model-First with EF
Model-First is a fantastic capability of the Entity Designer to allow you to focus on your conceptual model rather than the storage model when starting to build your application. The thing to keep in mind here is that Model-First uses TPT as the default inheritance mapping strategy when you build inheritance hierarchies.
Consider using TPH inheritance (along with Entity Designer Database Generation Power Pack)
TPH support is great from a performance perspective – and in many ways, TPH can help keep things simple as far as storage and query translation goes. TPH is an option within Model-First if you download and install the Entity Designer Database Generation Power Pack. A screenshot of the designer with the Entity Designer Power Pack installed are shown below:
We understand that there are scenarios where TPT is required and it is a goal of EF to provide the best possible performance when using all the inheritance mapping strategies supported out of the box. While the story is not perfect today with TPT, we hope that you are able to use some of the information mentioned above until we are able to release fixes for these in a future release.
Faisal Mohamood
Program Manager, Entity Framework
Absolute Beginners Guide to Entity Framework
To someone who has used emacs or a basic text editor for programming, jumping into Visual Studio 2010 can seem like going from a Cessna to a fighter jet. That’s the experience I had last week starting out at Microsoft, and my goal with this post is to provide others taking the plunge into the Entity Framework – or considering taking the plunge – with a handy guide for what it takes to get up and running. I hope that my fresh perspective will help you in a way that an experienced expert cannot.
The Essentials
The Entity Framework bridges the gap between how developers commonly manipulate conceptual objects (customers, orders, products; posts, tags, members; wall posts, private messages, friend connections) and the way data is actually stored (records in database tables). The technical term for a tool that provides this abstraction is object relational mapper (ORM). ORMs help developers be more efficient and focused, since they don't need to spend brain cycles thinking about how to communicate with the database. It also means that the code is more portable – switching database software requires changing a setting in the ORM, not a rewrite of the whole codebase to match the new database's dialect. As someone who has programmed using the ORM in Django, I can tell you how such a tool makes development less tedious and more enjoyable when you don't have to consider SELECTS and INSERTS. In fact, I've never before written a line of SQL, yet I was able to build a rich web application thanks to an ORM.
Getting Started
One of the nice features of using the Entity Framework is its out-of-the-box simplicity. To my pleasant surprise, I didn't need to download, install, or patch anything to get started with my first EF app. I booted up VS 2010, opened a new project, designed my entities, wrote my code, and off I went. You can probably get a very simple app up and running in about 10 minutes. To prove it, I'll do exactly that as a step-by-step walkthrough below. For this example, I'll make a simple events calendar.
Walkthrough
Begin by opening Visual Studio 2010.
From the 'File' menu select 'New' >> 'Project'. I’ve chosen Visual C# as my language and a Console Application as my format for simplicity. I will accept the default sequential naming that gets filled in for me, "ConsoleApplication2," so you can follow along by matching this with what gets filled in for you, too, though any real application should have an actual descriptive name such as "EventCalendar" or "PayrollProcessor."
Visual Studio will now set you up with a basic C# application. You may wish to rename the file from 'Program.cs' to something more meaningful to your project, but once again I'll stick with the default names so you can sync up and provide your own in its place.
The next step is adding your entities to the project. To do this, we’ll need to add a new file to our project which will contain the specifications for our entities. Open up the Solution Explorer panel. (If it’s not already in your workspace, you can bring it up by 'View' >> 'Solution Explorer'.) Right-click on the name of your application, in my case “ConsoleApplication2,” and click on the option 'Add' >> 'New Item'. Then, select 'ADO.NET Entity Data Model'. A good naming convention for your data model is to append the word "Model" to the end of your database name or application name, such as "EventCalendarModel" or "HumanResourcesModel."
If there was already a database in place that you had to use, then you would select the 'Generate from database' option, and the Entity Framework would do its best to create models and associations that fit the data. If you are starting an application from scratch and get to design the database, as I’ll be demonstrating in this walkthrough, select 'Empty model.' This is known as the model-first approach, instead of the database-first approach.
This will now open a new file – a canvas onto which you can design your data model. Rather than having to directly write the underlying XML file to specify the models and properties, this designer is a pretty slick way to configure your models and associate them. You start with an empty canvas.

Begin by adding you first entity. To add an entity, right-click on the design surface (the white canvas area) and click 'Add' >> 'Entity' from the context menu. As I mentioned before, I’m going to use an events calendar as my sample. We will have Users and Events as our two entities. Type a name for the entity, and notice how it automatically attempts to pluralize it in the EntitySet field. EntitySets are collections of entities (that map to tables in the database), which allow you to add, delete, or update entities (rows in the database). In other words, you'll be using this often in your code. Although the system usually gets the pluralization right, you can tweak it as you please. You can leave all of the other settings as their defaults to continue, unless you have a special need to customize them.

The new entity you created will now appear on the design surface. You can drag it around the designer as you please.

The next step will be to add properties to that entity. Properties are essentially "instance data" in the lexicon of object-oriented programming or "columns" in database parlance. You can add a property to an entity by right-clicking the entity and selecting 'Add' >> 'Scalar Property'. When you add the property, you can then name it whatever makes sense.

I’ll name the first one “Title” – the title of the Event. When you have one of the properties highlighted – while renaming it – you can simply press the 'Enter' key to keep adding more.
Notice how I left out one pretty important "property" – the Event's creator. That's because I plan to keep track of information about each User and which Events he creates, so a User of the calendar will be it's own entity that is associated with Events the User created. This type of property is called a 'navigation property'. As above, I add the User entity by right-clicking the canvas and clicking 'Add' >> 'Entity'.

I’ll now add two properties to it as above: a username and a password.
Finally, I'll add an association between the Event and the User to represent which User created an Event. To do this, right click anywhere on the design surface and select 'Add' >> 'Association'.
To configure the association:
1. Select the two “ends” of the association, or the two entities you will be associating, and their multiplicity to match the association you have in mind. In this case, I am setting up a many-to-one association between an Event and its creator; each Event has only one creator, but each User may have created many Events.
2. Since you may have multiple associations between the same two entities, it’s a good practice to be specific about the association name rather than just using the two entity names. I’ll name this “EventCreator” to be specific about what this association represents and avoid collisions or ambiguity.
3. Customize the navigation properties using terms that make sense relative to this relationship. Rather than just ‘User’ and ‘Events,’ I’ll use the terms ‘Creator’ and ‘CreatedEvents.’ These are the property names used by one entity to get to the other. You would use Event.Creator to get the single User who created that event and User.CreatedEvents for a list of events created by a certain User.

Click OK to create the relationship, and you will see this new linkage appear on the design surface. Notice how the multiplicity of the relationship is represented by the number 1 and the *, one and many, respectively. Also see how the new navigation properties have been added to each entity with the names specified.
To demonstrate why it makes sense to be specific with names of relationships and navigation properties, I’ll go one step further and allow Users to add Events to their personal calendar. I will keep track of this by a many-to-many relationship, a second association between an Event and a User. Here’s how that will look:

The extra association appears on the design surface, and the new navigation properties have been added to each entity. Notice how being specific with the naming of the navigation properties makes it very easy to understand – and use – the models, especially when there are multiple associations between the same two entities.

Now I will go through each scalar property I added before and verify that it has the right attributes. Right-click on any property of an entity and click the 'Properties' menu button. This will bring up the 'Properties' panel. Since I’ll be using this panel consistently while I make these tweaks, I decided to pin it to the right of my workspace by clicking the pushpin icon.

Although there's a lot to see in the properties panel, the most important parts right now are the 'Nullable' and 'Type' options specific to that property. I leave the other settings to a more advanced guide.
If you are using an ORM because you have limited database experience, then the term 'Nullable' may need some explanation. A property that is nullable is one that can contain a 'null' value. For example, if 'description' for an Event is optional, then it could be nullable (set this property to 'true'). If, however, you want to require that every Event must have a time, that field should not be nullable (false). In some senses, the word "optional" can be used as a loose analog.
The 'Type' property should be fairly familiar to a programmer – it's just the data type. So a time is probably best represented as a DateTime type, and an ID number is best stored as a 32-bit integer. One nice feature of the Entity Framework is how it abstracts the database underneath. Whereas one database may require a String, another may require that it be called a VarChar. When using the EF, this minor annoyance is abstracted by the database provider.
For this simple example, I have chosen to first add all of the names of the properties to each entity and then return to specify the type and nullability. You can also pause at any time while adding entities or properties to entities to do this.
Each property defaults to a string type. In this example, I've gone through and modified only the 'Time' property of the Event to make it a DateTime type. For all of the others, the default to string (or Int32 for keys) was appropriate.
Now my entities are ready, so it's time to ready the database and start writing code. Right click the canvas and select 'Generate Database from Model.'

From here, select the database connection you'd like to use, or select 'New Connection…'. I'll make a new connection in this example. The specifics of getting your database up and running are beyond the scope of this walkthrough. I happen to be borrowing a colleague's server. One notable feature I will cover is that you can specify a database name in the 'Select or enter a database name' field, and it will create a new database on the server for you if it one with that name does not already exist and you have the proper permissions. Note that clicking 'Test Connection' when you've specified a new database name (one to be created) will fail, since the database doesn't exist yet. Simply press 'OK' to establish the connection and attempt to create the database.

If creating a new database, you should see this dialog box:

Click 'Yes' to try to make the new database on the server. Assuming you've succeeded, you'll return to the original Generate Database Wizard and resume setting it up. The connection string, which tells the EF how to connect to the database, should be filled in for you. Click 'Next' to proceed. Make note of the value in the bottom field, which in my case is Model1Container. This will be needed later in the code to communicate with the database by forming a context.

After it's done thinking, you'll have a DDL file ready to go. Don't get tripped up by the term DDL; all we care about is that this file contains instructions for the database that will get it set up so that you can use your models with it.

This file contains the script that is appropriate for your database to set it up. Click 'Finish' to save that file. It will subsequently open up in VS, and may indicate that it is not connected to the database yet. The next step is to make that connection and run the script. Right-click inside the document and select 'Execute SQL'. Since I'm using SQL Server 2008, the window below pops up and I follow the steps to run the script. Depending on your database, what you have to do to execute that script may vary.
After the operation is complete, you'll get a confirmation that it was successful.
At this point, the database is all ready to go, and it's time to start interacting with it via code. Here’s a code snippet you can run if you were following along.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
/* In order to communicate with the database using the EF,
* set up a context as in the line below. Notice how 'Model1Container'
* follows through to here from where I mentioned it above. In order
* to interact with data from the database in any way, you must establish
* a context. */
using (Model1Container context = new Model1Container())
{
/* One way to create a new entity is to give it all of its
* values right away as below. Use the entity names from
* your model, and assign the properties that you can. */
User mike = new User
{
Username = "mike",
Password = "123456"
};
Console.WriteLine("Users before add: " + context.Users.Count()); // 0
/* Notice how the new user does not get added to the database or the context yet */
context.Users.AddObject(mike);
Console.WriteLine("Users before save: " + context.Users.Count()); // 0
/* At this point, the context knows about 'mike', but it hasn't yet
* saved 'mike' to the database. */
context.SaveChanges();
Console.WriteLine("Users after save: " + context.Users.Count()); // 1
/* Now 'mike' has been saved to the database. Any changes to 'mike' from
* this point forward will not be saved until context.SaveChanges() is
* called again. */
/* Here's an alternate approach to adding a new entity.
* You can continue assembling the entity at various parts of the code.
* Warning: Don't try to save an entity if one of its properties has not
* yet been set and that property is not nullable. */
User matt = new User();
matt.Username = "matt";
/* If you tried to save here, before setting 'Password', you'd get an error,
* since Password is not a nullable field. */
matt.Password = "654321";
context.Users.AddObject(matt);
context.SaveChanges();
/* Now it's possible to add an associated entity */
Event bbq = new Event
{
Title = "Barbeque",
Description = "BBQ at the office",
Time = new DateTime(2010, 07, 04, 18, 0, 0),
Location = "1 Microsoft Way, Redmond",
/* The simplicity in the following line is EF magic at work;
* setting up an association is effortless, despite the extra
* work done in the database for such a relationship */
Creator = mike
};
context.Events.AddObject(bbq);
context.SaveChanges();
/* Here, too, a many-to-many relationship becomes simple to establish
* despite the extra work being done in the database to organize this */
matt.ConfirmedEvents.Add(bbq);
context.SaveChanges();
/* Now we've got some meaningful data in the database to start querying */
/* One way to find something you’re looking for is by forming a query as follows.
* The "FirstOrDefault" should be used when you expect there to be only one entity
* with the properties you specify. */
User findMatt = context.Users.FirstOrDefault(user => user.Username == "matt");
Console.WriteLine("Found user: " + findMatt.Username);
/* Let's see how we can follow a navigation property. Since ConfirmedEvents
* is a navigation property for a many-to-many relationship, it will be
* something over which we can iterate in a foreach */
Console.WriteLine("Matt is attending " + findMatt.ConfirmedEvents.Count() + " events, including: ");
foreach (Event mattsEvents in findMatt.ConfirmedEvents)
{
Console.WriteLine(mattsEvents.Title);
}
/* We can also explore the many-to-many relationship in the other direction. */
Console.WriteLine("Attendees of the bbq:");
foreach (User attendee in bbq.Attendees)
{
Console.WriteLine(attendee.Username);
}
/* Pause at the end of execution */
Console.Read();
}
}
}
}
/* Output:
Users before add: 0
Users before save: 0
Users after save: 1
Found user: matt
Matt is attending 1 events, including:
Barbeque
Attendees of the bbq:
matt
*/
The code above belies the complexity of what is actually happening behind the scenes. This simplicity is what makes using the Entity Framework so powerful; it makes the developer’s job a lot easier. Beyond what I’ve been able to show in this brief walkthrough, there’s still plenty more to learn about the rest of the Entity Framework before you can fully realize its full potential. Here are some additional resources for going deeper:
Background on Entity Framework: http://channel9.msdn.com/posts/egibson/MSDN-Simulcast-All-DataAll-Day-Dive-into-NET-Data-Access-Deeper-Look-at-ADONET-Entity-Framework/
Great video tutorials: http://msdn.microsoft.com/en-us/data/videos.aspx
Quickstart Documentation: http://msdn.microsoft.com/en-us/library/bb399182.aspx
Helpful Glossary of Terms: http://msdn.microsoft.com/en-us/library/bb387161.aspx
Hub for all things EF: http://msdn.microsoft.com/en-us/library/bb399572.aspx
-Michael Yaroshefsky
Program Manager
Microsoft
EF Feature CTP4 Walkthrough: Code First
We recently announced the release of Entity Framework Feature Community Technology Preview 4 (CTP4) . Feature CTP4 contains a preview of new features that we are considering adding to the core framework in the future and would like to get community feedback on. Feature CTP4 builds on top of the existing Entity Framework 4 (EF4) functionality that shipped with .NET Framework 4.0 and Visual Studio 2010.
This post will provide a walkthrough of the fundamental components of the Entity Framework Code First feature. Our Productivity Improvement work, which is also included in CTP4, provides a streamlined Code First experience that reduces the amount of code you need to write by providing a façade on top of the building blocks described in this post. This experience is covered in our CTP4 Productivity Improvement Walkthrough.
If you need assistance with CTP4 we have an Entity Framework Pre-Release Forum.
If you haven’t already done so then you need to install Entity Framework Feature CTP4.
2. Create the ApplicationTo keep things simple we’re going to build up a basic console application that uses Code First to perform data access.
· Open Visual Studio 2010
· File -> New -> Project…
· Select “Windows” from the left menu and “Console Application”
· Enter “EF.CodeFirst.Walkthrough” as the name
· Select “OK”
3. Create the ModelCode First is all about describing our model using classes so we are going to start by building out a simple model in code. We want our model to be persistence ignorant (i.e. not have any dependencies on Entity Framework) so we’ll add our model in a separate project.
· Add a new project for the model
o File -> Add -> New Project…
o Select “Windows” from the left menu and “Class Library”
o Enter “EF.CodeFirst.Walkthrough.Model” as the name
o Select “OK”
· Right click on the model project and add a class called “Book” with the following implementation
using System;
namespace EF.CodeFirst.Walkthrough.Model
{
public class Book
{
public string ISBN { get; set; }
public string Title { get; set; }
public DateTime FirstPublished { get; set; }
public bool IsFiction { get; set; }
public virtual Publisher Publisher { get; set; }
public virtual Author Author { get; set; }
}
}
· Right click on the model project and add a class called “Person” with the following implementation
namespace EF.CodeFirst.Walkthrough.Model
{
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
· Right click on the model project and add a class called “Author” with the following implementation
using System.Collections.Generic;
namespace EF.CodeFirst.Walkthrough.Model
{
public class Author : Person
{
public int AuthorId { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}
· Right click on the model project and add a class called “Publisher” with the following implementation
using System.Collections.Generic;
namespace EF.CodeFirst.Walkthrough.Model
{
public class Publisher
{
public int PublisherId { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}
4. Model Builder & Fluent APIIf you’ve used the previous CTPs of Code First then this is where things to start to look a little different. As the name suggests ModelBuilder is used to configure the model, ModelBuilder then produces an immutable DbModel that can be used to construct either ObjectContext or DbContext instances.
Once you have created a DbModel this should be cached and re-used throughout your application to avoid incurring the performance hit of model creation multiple times. If you opt for the Code First approach described in the Productivity Improvements walkthrough then DbContext takes care of this caching for you.
· First we need to reference our model from the main application
o Right click on the console application project -> Add Reference…
o Select the “Project” tab
o Select the model project from the list
o Click “OK”
· We also need to reference the CTP4 assembly and the core Entity Framework assembly
o Right click on the console application project -> Add Reference…
o Select the “.NET” tab
o Select “Microsoft.Data.Entity.Ctp” from the list
o Click “OK”
o Repeat the above steps for “System.Data.Entity”
· We also need to add a few using statement to the top of Program.cs
using System.Data.Entity.ModelConfiguration;
using System.Data.SqlClient;
using EF.CodeFirst.Walkthrough.Model;
· Next add the following code to the Main method in Program.cs to configure your model
static void Main(string[] args)
{
var builder = new ModelBuilder();
builder.Entity<Book>().HasKey(b => b.ISBN);
builder.Entity<Book>().Property(b => b.Title).IsRequired();
builder.Entity<Book>().HasRequired(b => b.Author).WithMany(a => a.Books);
builder.Entity<Person>();
builder.Entity<Publisher>().Property(p => p.Name).IsRequired().HasMaxLength(50);
}
Note: In the final section we will cover creating a derived context that exposes sets for the types in your model. Once you have a derived context you can use the ModelBuilder.DiscoverEntitiesFromContext(Type contextType) method to have the types that are exposed in sets automatically registered for you. This avoids the need to manually register types that do not require any additional configuration, such as Person in the code above.
Why Introduce DbModel?
In previous CTPs ContextBuilder basically did the work of both ModelBuilder and DbModel, introducing a separate representation for the final model does add an extra step in the process. In the future DbModel will become more fundamental to EF in general as we look at other ways to build models beyond ModelBuilder. DbModel allow us to have a single representation for a model that can then be used to construct both ObjectContext and DbContext instances.
Conventions
You’ll notice there are a lot of things I’m not specifying about the model, for example that Person.PersonId is a primary key or that Book.Publisher and Publisher.Books are inverse navigation properties of the same relationship. This is because Code First now includes an extended set of conventions to take care of common configuration tasks for you. The conventions are discussed in detail in this Conventions design blog post, the conventions included in CTP4 are:
- Primary Key
- Relationship Inverse
- Foreign Key
- Pluralization of Table Names
Any configuration that you specify explicitly via the Fluent API will take precedence over what is discovered via convention.
Data Annotations
Code First will also now consume Data Annotations so rather than configuring Book.ISBN as the primary key via the Fluent API we could have added the Key attribute (System.ComponentModel.DataAnnotations.KeyAttribute) to the ISBN property.
Data Annotations are described in detail in this design blog post, the annotations supported in CTP4 are:
- Key
- StringLength
- ConcurrencyCheck
- Required
- Timestamp
- DataMember
- RelatedTo
- MaxLength
- StoreGenerated
Data Annotations take precedence over conventions but explicit configuration via the Fluent API still has the highest precedence.
Relationship API Changes
If you’ve used the previous CTPs of Code First you’ll also notice we have changed the syntax for specifying relationships in an attempt to make it more intuitive. The single Relationship method has now been replaced with HasRequired, HasOptional and HasMany. Inverse navigations are then specified via WithRequired, WithOptional and WithMany. If you expose foreign key properties on your entities then these can be configured via the HasConstaint method.
The main benefits of the refactoring are:
- Reduced number of calls required to configure a relationship
-
API Signatures are more understandable
- The single Relationship method with overloads for references and collections was proving to be confusing
-
Removal of invalid methods
- The previous API exposed Required and Optional for ‘many’ ends of relationships
- Ability to full specify relationships that only expose one navigation property
Using the one-to-many relationship between Book and Author as an example, this would previously have been configured as follows
builder.Entity<Book>().Relationship(b => b.Author).IsRequired().FromProperty(a => a.Books);
With the API changes this is now
builder.Entity<Book>().HasRequired(b => b.Author).WithMany(a => a.Books);
If the Author.Books property was not included in the model it is now possible to still completely specify the relationship
builder.Entity<Book>().HasRequired(b => b.Author).WithMany();
Or alternatively if the Book.Author property was not included
builder.Entity<Author>().HasMany(a => a.Books).WithRequired();
5. Configuration ClassesNow let’s say we want to encapsulate the configuration for Book in a separate class. We can do this by creating a derived configuration class for Book and then registering it with our model builder. This is useful if you want to re-use configurations within an application or even between applications. Configuration classes also nicely separate configuration related code from the rest of our application code.
· Right click on the console application project and add a class called “BookConfiguration” with the following implementation
using System.Data.Entity.ModelConfiguration;
using EF.CodeFirst.Walkthrough.Model;
namespace EF.CodeFirst.Walkthrough
{
public class BookConfiguration : EntityConfiguration<Book>
{
public BookConfiguration()
{
this.HasKey(b => b.ISBN);
this.Property(b => b.Title).IsRequired();
this.HasRequired(b => b.Author).WithMany(a => a.Books);
}
}
}
· We can then modify the Main method in Program.cs to be as follows
static void Main(string[] args)
{
var builder = new ModelBuilder();
builder.Configurations.Add(new BookConfiguration());
builder.Entity<Person>();
builder.Entity<Publisher>().Property(p => p.Name).IsRequired().HasMaxLength(50);
}
6. Create a Derived ContextNow that we have a model configured the easiest way to interact with the classes is through a derived context. With the introduction of the Productivity Improvements that we mentioned earlier there are two options here. You can either derive from our existing ObjectContext type or the new alternative DbContext type, which has a simpler API surface. We’ll look at both options in this walkthrough.
· Right click on the console application project and add a class called “BookCatalog” with the following implementation
using System.Data.EntityClient;
using System.Data.Objects;
using EF.CodeFirst.Walkthrough.Model;
namespace EF.CodeFirst.Walkthrough
{
public class BookCatalog : ObjectContext
{
public BookCatalog(EntityConnection connection)
: base(connection)
{ }
private ObjectSet<Book> _books;
public ObjectSet<Book> Books
{
get
{
return this._books == null
? this._books = this.CreateObjectSet<Book>()
: this._books;
}
}
private ObjectSet<Person> _people;
public ObjectSet<Person> People
{
get
{
return this._people == null
? this._people = this.CreateObjectSet<Person>()
: this._people;
}
}
private ObjectSet<Publisher> _publishers;
public ObjectSet<Publisher> Publishers
{
get
{
return this._publishers == null
? this._publishers = this.CreateObjectSet<Publisher>()
: this._publishers;
}
}
}
}
· With a derived context defined we can now modify the Main method in Program.cs to use it for data access:
static void Main(string[] args)
{
var builder = new ModelBuilder();
builder.Configurations.Add(new BookConfiguration());
builder.Entity<Person>();
builder.Entity<Publisher>().Property(p => p.Name).IsRequired().HasMaxLength(50);
var model = builder.CreateModel();
using (var connection = new SqlConnection(@"Server=.\SQLEXPRESS;Database=CodeFirstWalkthrough;Trusted_Connection=True;"))
{
using (var context = model.CreateObjectContext<BookCatalog>(connection))
{
if (!context.DatabaseExists())
{
context.CreateDatabase();
}
var book = new Book
{
ISBN = "1111",
Title = "Intro to Code First",
FirstPublished = DateTime.Today,
IsFiction = false,
Author = new Author { FirstName = "Rowan", LastName = "Miller" },
Publisher = new Publisher { Name = "EF Books" }
};
context.Books.AddObject(book);
context.SaveChanges();
}
}
}
We’re going to look at constructing a DbContext from a DbModel but as previously mentioned there is simpler Code First experience available that avoids the need to externally create a ModelBuilder and DbModel and also takes care of model caching, this is described in the Productivity Improvements walkthrough.
· Right click on the console application project and add a class called “SimpleBookCatalog” with the following implementation:
using System.Data.Entity;
using EF.CodeFirst.Walkthrough.Model;
using System.Data.Entity.Infrastructure;
namespace EF.CodeFirst.Walkthrough
{
public class SimpleBookCatalog : DbContext
{
public SimpleBookCatalog(DbModel model)
: base(model)
{ }
public DbSet<Book> Books { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<Author> Authors { get; set; }
public DbSet<Publisher> Publishers { get; set; }
}
}
· With a derived context defined we can now modify the Main method in Program.cs to use it for data access
Note that DbContext takes care of creating a database for us so we don’t need to specify a connection, this convention can be overridden and is described in the Productivity Improvements walkthrough.
static void Main(string[] args)
{
var builder = new ModelBuilder();
builder.Configurations.Add(new BookConfiguration());
builder.Entity<Person>();
builder.Entity<Publisher>().Property(p => p.Name).IsRequired().HasMaxLength(50);
var model = builder.CreateModel();
using (var context = new SimpleBookCatalog(model))
{
var book = new Book
{
ISBN = "2222",
Title = "Intro to Code First",
FirstPublished = DateTime.Today,
IsFiction = false,
Author = new Author { FirstName = "Rowan", LastName = "Miller" },
Publisher = new Publisher { Name = "EF Books" }
};
context.Books.Add(book);
context.SaveChanges();
}
}
7. SummaryIn this walkthrough we looked at how the fundamental Code First components can be used to configure a model and create a context to perform data access. We saw the extended default conventions, Data Annotations and the updated relationship API that are new in CTP4.
As mentioned during the post these building blocks are also used to provide a simpler and more streamlined Code First experience in the Productivity Improvement work described in this post.
Rowan Miller
Program Manager
ADO.NET Entity Framework
EF Feature CTP4 Walkthrough: Productivity Improvements
We recently announced the release of Entity Framework Feature Community Technology Preview 4 (CTP4) . Feature CTP4 contains a preview of new features that we are considering adding to the core framework in the future and would like to get community feedback on. Feature CTP4 builds on top of the existing Entity Framework 4 (EF4) functionality that shipped with .NET Framework 4.0 and Visual Studio 2010.
If you need assistance with CTP4 we have an Entity Framework Pre-Release Forum.
This walkthrough provides an introduction to the Productivity Improvement work that is included in our Entity Framework Feature CTP4 release. Our recent Design Blog post provides a detailed background on the Productivity Improvements, here is a quick summary extract from that post:
We’ve been paying attention to the most common patterns that we see developers using with the EF and have been brewing up a set of improvements to the Entity Framework designed to allow developers to accomplish the same tasks with less code and fewer concepts.
These improvements provide a cleaner and simpler API surface that focuses your attention on the most common scenarios but still allows you to drill down to more advanced functionality when it’s needed. We hope you will enjoy this simpler experience, but we should be quick to assure you that this is NOT a new data access technology. These improvements are built on the same technology for mapping, LINQ, providers and every other part of the Entity Framework.
Database First & Model First
The Productivity Improvement work benefits developers using Database First, Model First and Code First development patterns. This walkthrough will use the Code First development pattern. The T4 Templates to support Database First and Model First development didn’t make it into CTP4 but we will provide some sample templates in a separate post in the coming weeks.
1. Install EF CTP4If you haven’t already done so then you need to install Entity Framework Feature CTP4.
2. Create the ApplicationTo keep things simple we’re going to build up a basic console application that uses the EF Productivity Improvements to perform data access.
· Open Visual Studio 2010
· File -> New -> Project…
· Select “Windows” from the left menu and “Console Application”
· Enter “EF.PI.Walkthrough” as the name
· Select “OK”
3. Create the ModelLet’s define a very simple model using classes. I’m just defining them in the Program.cs file but in a real world application you would split your classes out into separate files and probably a separate project.
· Below the Program class definition in Program.cs I am defining the following two classes
public class Category
{
public string CategoryId { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public string CategoryId { get; set; }
public virtual Category Category { get; set; }
}
4. Create a Context
The simplest way to start using the classes for data access is to define a context that derives from System.Data.Entity.DbContext and exposes a typed DbSet<TEntity> for each class in my model.
· We’re now starting to use types from the CTP so we need to add a reference to the CTP assembly
o Project -> Add Reference…
o Select the “.NET” tab
o Select “Microsoft.Data.Entity.Ctp” from the list
o Click “OK”
· You’ll also need a reference to the existing Entity Framework assembly
o Project -> Add Reference…
o Select the “.NET” tab
o Select “System.Data.Entity” from the list
o Click “OK”
· Add a using statement for System.Data.Entity at the top of Program.cs
using System.Data.Entity;
· Add a derived context below the existing classes that we’ve defined
public class ProductCatalog : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
That is all the code we need to write to start storing and retrieving data. Obviously there is quite a bit going on behind the scenes and we’ll take a look at that in a moment but first let’s see it in action.
5. Access Data
· I’m padding out the Main method in my program class as follows
class Program
{
static void Main(string[] args)
{
using (var context = new ProductCatalog())
{
var food = new Category { CategoryId = "FOOD", Name = "Foods" };
context.Categories.Add(food);
int recordsAffected = context.SaveChanges();
Console.WriteLine(
"Saved {0} entities to the database, press any key to exit.",
recordsAffected);
Console.ReadKey();
}
}
}
You can now run the application and see that the new category is inserted.
Where’s My Data?
DbContext has created a database for you on localhost\SQLEXPRESS. The database is named after the fully qualified name of your derived context, in our case that is “EF.PI.Walkthrough.ProductCatalog”. We’ll look at ways to change this later in the walkthrough.
Model Discovery
DbContext worked out what classes to include in the model by looking at the DbSet properties that we defined. It then uses the default Code First conventions to find primary keys, foreign keys etc. The conventions are discussed in detail in this Conventions Design Blog post, the conventions included in CTP4 are:
- Primary Key
- Relationship Inverse
- Foreign Key
-
Pluralization of Table Names
Simplified API Surface
If you’re familiar with ObjectContext you’ll notice that intellisense on your derived context now only shows you 10 members, as opposed to the 47+ that showed up on ObjectContext.
You’ll see we have started to factor functionality away so that only the most commonly used operations are exposed at the root level. For example all members related to the underlying database are available from context. Database. This is just one example of the work we are doing to provide a more discoverable and intuitive API surface, more detail is available in the API Surface section of our Productivity Improvements Design Blog post.
6. Access More DataLet’s pad out the program we just wrote to show a bit more functionality. We are going to make use of the Find method on DbSet that will locate an entity based on primary key. If no match is found then Find will return null. We’re also making use of LINQ to query for all products in the Food category ordered alphabetically by name. Querying uses the exiting LINQ to Entities provider so it supports the same queries that are possible with ObjectSet/ObjectQuery in EF4.
· I’m replacing the Main we wrote above with the following
class Program
{
static void Main(string[] args)
{
using (var context = new ProductCatalog())
{
// Use Find to locate the Food category
var food = context.Categories.Find("FOOD");
if (food == null)
{
food = new Category { CategoryId = "FOOD", Name = "Foods" };
context.Categories.Add(food);
}
// Create a new Food product
Console.Write("Please enter a name for a new food: ");
var productName = Console.ReadLine();
var product = new Product { Name = productName, Category = food };
context.Products.Add(product);
int recordsAffected = context.SaveChanges();
Console.WriteLine(
"Saved {0} entities to the database.",
recordsAffected);
// Query for all Food products using LINQ
var allFoods = from p in context.Products
where p.CategoryId == "FOOD"
orderby p.Name
select p;
Console.WriteLine("All foods in database:");
foreach (var item in allFoods)
{
Console.WriteLine(" - {0}", item.Name);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
7. Changing the Database Name
If you want to change the name of the database that is created for you then there is a constructor on DbContext that allows you to specify the name.
· Say we want to change the name of the database to “MyProductCatalog” we could add a default constructor to our derived context that passes this name down to DbContext:
public class ProductCatalog : DbContext
{
public ProductCatalog()
: base("MyProductCatalog")
{ }
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
Other Ways to Change the Database
There are a number of other ways to specify which database should be connected to. We’ll cover these in more detail in a separate post in the near future.
-
App.config Connection String
Create a connection string in the App.Config file with the same name as your context. -
DbConnection
There is a constructor on DbContext that accepts a DbConnection. -
Replace the Default Convention
The convention used to locate a database based on the context name is an AppDomain wide setting that you can change via the static property System.Data.Entity.Infrastructure.Database.DefaultConnectionFactory.
In the next section we are going to start changing our model which in turn means the database schema needs to change as well. Currently there is no out of the box solution to migrate your existing schema in place, although this is something we are looking at addressing. There is however the opportunity to run some custom logic to initialize the database the first time a context is used in an AppDomain. This is handy if you want to insert seed data for test runs but it’s also useful to re-create the database if the model has changed. In CTP4 we include a couple of strategies you can plug in but you can also write custom ones.
For the walkthrough we just want to drop and re-create the database whenever the model has changed.
· At the top of the Main method in my Program class I’ve added the following code
Database.SetInitializer<ProductCatalog>(new RecreateDatabaseIfModelChanges<ProductCatalog>());
We’ll provide more details on this feature and the scenarios that it enables in a separate post.
9. Data AnnotationsSo far we’ve just let EF discover the model using its default conventions but there are going to be times when our classes don’t follow the conventions and we need to be able to perform further configuration. There are two options for this; we’ll look at Data Annotations in this section and then the Code First Fluent API in the next section.
· Let’s add a supplier class to our model
public class Supplier
{
public string SupplierCode { get; set; }
public string Name { get; set; }
}
· And we also need to add a set to our derived context
public class ProductCatalog : DbContext
{
public ProductCatalog()
: base("MyProductCatalog")
{ }
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
}
Now if we ran our application we’d get an InvalidOperationException saying “Unable to infer a key for entity type 'EF.PI.Walkthrough.Supplier'.” because EF has no way of knowing that SupplierCode should be the primary key for Supplier.
· We’re going to use Data Annotations now so we need to add a reference
o Project -> Add Reference…
o Select the “.NET” tab
o Select “System.ComponentModel.DataAnnotations” from the list
o Click “OK
· Add a using statement at the top of Program.cs
using System.ComponentModel.DataAnnotations;
· Now we can annotate the SupplierCode property to identify that it is the primary key:
public class Supplier
{
[Key]
public string SupplierCode { get; set; }
public string Name { get; set; }
}
Data Annotations are described in detail in this Design Blog post, the annotations supported in CTP4 are:
- Key
- StringLength
- ConcurrencyCheck
- Required
- Timestamp
- DataMember
- RelatedTo
- MaxLength
- StoreGenerated
We looked at configuring the model using Data Annotations but you may not want to add attributes to your classes or in some cases you may not be able to if they belong to another class library. The other option is to use the Code First Fluent API within DbContext.
Let’s say we want to configure Name to be a required property for Supplier.
· Add a using statement for System.Data.Entity.ModelConfiguration at the top of Program.cs
using System.Data.Entity.ModelConfiguration;
· Override the OnModelCreating method in the derived context, as highlighted below
Note: The base implementation of OnModelCreating is blank so there is no need to call the base method.
public class ProductCatalog : DbContext
{
public ProductCatalog()
: base("MyProductCatalog")
{ }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Supplier>().Property(s => s.Name).IsRequired();
}
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
}
SummaryIn this walkthrough we looked at the core patterns for Code First development using the EF Productivity Improvements included in EF Feature CTP4. We looked at defining and configuring a model, storing and retrieving data, configuring the database connection and updating the database schema as our model evolved.
We’d like to hear any feedback you have on these new Productivity Improvements for EF.
Rowan Miller
Program Manager
ADO.NET Entity Framework
EF Feature CTP4 Released!
We’ve release an updated Entity Framework Feature Community Technology Preview (CTP) which is available for download. This is our fourth CTP and includes updates to the Code First feature along with the first preview of our Productivity Improvements for EF.
Feature CTP4 contains a preview of new features that we are considering adding to the core framework in the future and would like to get community feedback on. Feature CTP4 builds on top of the existing Entity Framework 4 (EF4) functionality that shipped with .NET Framework 4.0 and Visual Studio 2010.
We’ve created a couple of walkthroughs to get you started with these new features, we’ll also be providing more detailed posts that dive down into interesting areas of each feature in the coming weeks.
If you need assistance with CTP4 we have an Entity Framework Pre-Release Forum.
Productivity ImprovementsWe recently posted here about a set of productivity improvements we have been working on to simplify the process of writing data access code with the Entity Framework. CTP4 includes the core API surface and functionality that is described in the post. We’d love to hear your feedback on this simplified experience, be sure to check out the walkthrough.
Code FirstUpdates and enhancements to Code First include:
- Moved to the System.Data.Entity.ModelConfiguration namespace
-
Refactored ContextBuilder into ModelBuilder and DbModel
ModelBuilder is a high level component that lets you tweak a model, ModelBuilder then produces an immutable DbModel that can be used to construct a context. In the future DbModel will become a fundamental component of the EF stack as we look at other ways to build models beyond ModelBuilder. -
More Model Discovery Conventions
We posted details about the complete set of conventions we plan to support here
In CTP4 we have implemented the following conventions:- Primary Key
- Relationship Inverse
- Foreign Key
- Pluralization of Table Names
-
Support for Data Annotations
We posted details about all the Data Annotations we plan to support here
The annotations supported in CTP4 are:- Key
- StringLength
- ConcurrencyCheck
- Required
- Timestamp
- DataMember
- RelatedTo
- MaxLength
- StoreGenerated
-
Parameterless overload of MapSingleType()
This allows you to configure table names without having to explicitly map every property -
Improved Relationship Configuration API
We’ve made some changes to the Fluent API methods used to configure relationships to make the API more explicit and intuitive. These changes are covered in the Code First Walkthrough .
We are still working through the best ship vehicle to deliver a go-live release for these features. Your feedback has had a big impact on the Code First feature so far and we want to be careful not to lock down the API too quickly. That said we are getting consistent asks for a go-live for Code First and we are working to get to an RTM in the earliest feasible ship vehicle.
Please keep the feedback coming!
ADO.NET Entity Framework Team








