次の方法で共有


EF Feature CTP4 Walkthrough: Code First

 


The information in this post is out of date.

Visit msdn.com/data/ef for the latest information on current and past releases of EF.

For Code First to a New Database see https://msdn.com/data/jj193542

For Code First to an Existing Database see https://msdn.com/data/jj200620


 

Introduction

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.

1. Install EF CTP4

If you haven’t already done so then you need to install Entity Framework Feature CTP4.

2. Create the Application

To 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 Model

Code 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 API

If 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 Classes

Now 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 Context

Now 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.

6.1. Option 1: Object Context

· 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();

        }

    }

}

 

6.2. Option 2: DbContext

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. Summary

In 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.CodeFirst.Walkthrough.zip

Comments

  • Anonymous
    July 14, 2010
    How can I map a property "Name" to a database field with the name ProductName ? In Fluent NHibernate you can write Map(x=>x.Name,"ProductName");

  • Anonymous
    July 14, 2010
    I really like what i am seeing. But, ... do you support enums ?

  • Anonymous
    July 14, 2010
    The comment has been removed

  • Anonymous
    July 15, 2010
    Hi, I'm jumping into CTP 4. My database is in Spanish so the english pluralization conventions don't work for me. The problem is that I can't make ModelBuilder to understand that I want my entity "Poblacion" mapped to the table "Poblaciones". I have tried

  1.  _modelBuilder.RegisterSet<Poblacion>("Poblaciones");
  2. _modelBuilder.Entity<Poblacion>().MapSingleType().ToTable("Poblaciones") None of these have been succesfull and I get a pretty "EntityCommandExecutionException" that wraps the SqlException telling me that the object "dbo.Poblacions" (english pluralization) is not valid as it doesn't exist in my database. With CTP 3 ContextBuilder.RegisterSet<T>(string name) did the trick. Any help would be appreciated. Thanks! Germán
  • Anonymous
    July 15, 2010
    @Martin Nyborg You can specify column names using the MapSingleType method, you can also optionally include ToTable to specify the table name. In CTP4 this does require you to specify all properties that you want included in the table and not just the ones you want to rename. In the future we’ll support a ColumnName attribute you can put in your classes and also the ability to rename a single column through the Fluent API without having to specify every property. builder.Entity<Product>()    .MapSingleType(p => new { p.ProductId, ProductName = p.Name })    .ToTable("Products");

  • Anonymous
    July 15, 2010
    @MartinF Enums are not available in EF4 (.NET 4.0/Visual Studio 2010) or CTP4, they are however one of the most common outstanding asks and our team is working on them at the moment.

  • Anonymous
    July 15, 2010
    @Chris This is an interesting idea, thanks for the input! One of the reasons Database and Set<T> are public is because you can create an instance of DbContext<T> without needing to create a derived context. Then you can use Set<T> to work with the types in your model.

  • Anonymous
    July 15, 2010
    @Germán _modelBuilder.Entity<Poblacion>().MapSingleType().ToTable("Poblaciones"); is the correct way to rename the table I think the issue you are hitting is that the old database that was originally created with the incorrect table name is still present and isn’t getting replaced with the new schema. We don’t have a good schema migration story yet (but we are working on it) so you can either manually delete the database or update the code to always delete and recreate the database:  if (context.DatabaseExists())  {      context.DeleteDatabase();  } If you are using DbContext rather than ObjectContext then you can write code to only re-create the database when the model actually changes:  if (!context.Database.ModelMatchesDatabase())  {      context.Database.DeleteIfExists();      context.Database.Create();  }

  • Anonymous
    July 15, 2010
    This is great news!  We're building our app based on Code First, and the experience has been excellent. The model of POCO classes for entities really works for us, and the DataAnnotations will make it even better.  We're also eager for an RTM. Other than what you've mentioned already, there's one more thing we'd love to see in the release -- is there any chance support for stored procedures & user defined functions will be added (without resorting to ExecuteStoreQuery to run T-SQL)?  Native support would let us include SP's and UDF's as subqueries in larger LINQ queries.

  • Anonymous
    July 15, 2010
    @Rowan: Is there support for "one-way" many-to-many like here social.msdn.microsoft.com/.../6920db2b-88c7-4bea-ac89-4809882cff8f Also - Where is the ability to map the StoreTableName like with CTP3?

  • Anonymous
    July 15, 2010
    @TheCloudlessSky Yes this is supported with a parameterless overload of the WithXXX relationship methods:   modelBuilder.Entity<Post>().HasMany(p => p.Tags).WithMany(); The syntax for specifying table names is the same as in CTP3, we also introduced a parameterless overload of MapSingleType so you don't have to explicitly map every column just to rename the table:    modelBuilder.Entity<Category>().MapSingleType().ToTable("CategoryTable");

  • Anonymous
    July 15, 2010
    @Rowan, modelBuilder.Entity<Poblacion>().MapSingleType().ToTable("dbo.Poblaciones") I can't make this work. The configuration "dbo.Poblaciones" simply does not get all the way through the ObjectContext and MetadataWorkspace. It may have something to do with these methods deep in the MetadaWorkspace generation phase from a ModelBuilder. EntityContainerGenerator.GenerateEntityDefinitions() EntityContainerInfo.AddEntityType(Type clrType, EntityTypeInfo rootType, EntityTypeInfo baseType, StoreTableName tableName) Saludos!! Germán

  • Anonymous
    July 15, 2010
    Just in case anybody else is having the same problem registering the right table names with CTP 4 ModelBuilder's MapSingleType() and ToTable() methods, I have found this workaround explained here: blogs.microsoft.co.il/.../change-entity-framework-storage-db-schema-in-runtime.aspx It looks horrible, I know. Germán DbModel _model; // created by ModelBuilder in CTP4        public ObjectContext CreateContext()        {                        var context = _model.CreateObjectContext<ObjectContext>(connection);                        context.ContextOptions.LazyLoadingEnabled = true;            FixContextTableNames(context);            return context;        }        void FixContextTableNames(ObjectContext context)        {            var fixNames = new List<Tuple<string,string>>();            fixNames.Add(Tuple.Create("Destinoes", "Destinos"));            fixNames.Add(Tuple.Create("Catalogoes", "Catalogos"));            fixNames.Add(Tuple.Create("Hotels", "Hoteles"));            fixNames.Add(Tuple.Create("MediaAlbums", "MediaAlbum"));            fixNames.Add(Tuple.Create("Poblacions", "Poblaciones"));            var container = context.MetadataWorkspace.GetItem<EntityContainer>("EntitiesStoreContainer", DataSpace.SSpace);                        foreach(var t in fixNames)            {                var entitySet = container.BaseEntitySets[t.Item1];                typeof(EntitySetBase).GetField("_table", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(entitySet, t.Item2);            }                    }

  • Anonymous
    July 16, 2010
    Will it be possible to use CodeFirst's syntax and design to simply do the 'mapping' part of our code, instead of having it build the database? A lot of us have our data, and we just want to map to it, but the UI designer is insufficient because of its quirks, this is why the CodeFirst appealed to us.

  • Anonymous
    July 16, 2010
    @Derek I have exactly the same vision as you. I don't want EF to recreate the database and I also don't like the designer experience. Whith today's CTP I think this can be achieved so:    public class DontTouchMyDatabase<TContext> : IDatabaseInitializer<TContext> where TContext: DbContext    {        public void InitializeDatabase(TContext context) {            // just don't do nothing        }    } // somewhere in you main or in your app initialize code: Database.SetInitializer<MyDerivedDbContext>(new DontTouchMyDatabase<MyDerivedDbContext>());

  • Anonymous
    July 16, 2010
    @Derek & @Germán If you are using an ObjectContext based context then it will never try and create a database for you, you have to explicitly call CreateDatabase() etc. By default DbContext will only try to create the database if it doesn’t already exist, so if you point it to an existing database then it won’t try and re-create it (we chose this behavior to allow both creating a new database and mapping to an existing database). If you would rather have the context throw if the database doesn’t exist (rather than trying to create one) then you can just register a null initializer:    Database.SetInitializer<ProductContext>(null); It is possible to map to an existing database using ModelBuilder to specify column and table names, we are seeing a number of people taking this approach. @Germán I tried to reproduce the issue you are seeing but it successfully changes the table name for me so there must be something subtly different between our code, any chance you send me the code that is failing for you so I can work out what the issue is; “rowmil AT microsoft DOT com” We definitely don’t expect you to have to start manipulating metadata to achieve this. We have a Pre-Release Forum which is a good place to post technical questions about the CTPs, you should get faster responses and it also keeps proper formatting in code samples :) social.msdn.microsoft.com/.../threads

  • Anonymous
    July 16, 2010
    Loving the new code-first option and the DbContext class.  Question though, is there a way to use WCF Data Services with the new DbContext?  I'm very close, but falling over on turning off ProxyCreationEnabled.  DbContext doesn't expose and ContextOptions, so there's not property to set.  Is there a workaround without using an ObjectContext and losing the benefits of the DbContext? -Damien

  • Anonymous
    July 17, 2010
    Will you support using diffrent types of Id generators like etc. a HiLo generator to be able to assign ids to the pocos before saving to the database and thereby doing all work in one batch without having to do a select (Scope_identity()) after each insert ? Will it be a problem if the DbContext class (the one that inherits from it) includes 20-30-40 DbSets (one for each table)? Should it be split into smaller parts or all kept in one ? Is the DbContext something that you would instantiate only 1 time during the lifetime of a webapplication by using the singleton pattern for an example or is it a lightweight operation and it could be created whenever needed or maybe once for every request by a httpModule ?

  • Anonymous
    July 18, 2010
    This is awesome. Does RIA Services support EF Feature CTP4 Code First? I would like to use these new features in Silverlight (4), instead of ServiceContext : LinqToEntitiesDomainService<EntityModel>.

  • Anonymous
    July 18, 2010
    This is really nice stuff. I have a question I'd like to see answered in a future post though. What are effective strategies of maintaining the database as the design evolves over time?

  • Anonymous
    July 18, 2010
    Thanks for the new release!!! I want to add properties to my model but they must not appear in the database. Currently when I add a complex property like List<Customers> CustomersXXX  to the SalesPerson class it tries to find a table like CustomersXXX_SalesPerson or something like that. I need to find a way to tell the ModelBuilder to ignore some of the properties. They do not map to anything the the database!!!

  • Anonymous
    July 19, 2010
    The comment has been removed

  • Anonymous
    July 19, 2010
    The comment has been removed

  • Anonymous
    July 21, 2010
    Thanks for this grt post. Can we use stored procedure with CTP4.

  • Anonymous
    July 21, 2010
    Using CTP3 I managed to have something like POCOBase Person:POCOBase Company:POCOBase Using EntityConfiguration for each derived class it was generating TPT. The entity configurations are composed with MEF in MyContextBuilder:ContextBuilder   Using the (almost) same code with CTP4, it generates TPH - Person & Company are merged in one table. How can I get back to TPT generation, without having to specify all the fields in the configuration class?

  • Anonymous
    July 22, 2010
    Awesome relese, thanks. I've a question. There's a way to disable pluralization? thanks in advance

  • Anonymous
    July 22, 2010
    The comment has been removed

  • Anonymous
    July 23, 2010
    The comment has been removed

  • Anonymous
    July 23, 2010
    Nice stuff. Whats the target date for a RTM?

  • Anonymous
    July 26, 2010
    Hi, I am new to CTP4, there is a mapping question. For Northwind database, there is Employees, Territories and EmployeeTerritories table, how do I write the configuration for Employee and Territories to retrieve Territories from Employee correctly? Thanks a lot.

  • Anonymous
    July 26, 2010
    good to see the fluent nhibernate features like automapping in this release. good job.

  • Anonymous
    July 26, 2010
    What if I have case like "a null reference to Author from book". The following code still apply? If not what is the appropriate command? builder.Entity<Book>().HasRequired(b => b.Author).WithMany(a => a.Books);

  • Anonymous
    July 28, 2010
    When could we expect release of full production code first? New project for me on horizon and I'd like to use entity framework as an alternative to nhibernate. Of course, it's not possible now because it's not released as ready product.

  • Anonymous
    July 28, 2010
    I'm liking the new Code First convention and after a bit of a struggle I think I've worked out how to map my POCOs to my existing database. At the moment DbContext automatically maps entity collections to public IDbSet<T> properties. Is it possible to map to properties which implement IDbSet<T>? eg: public interface IRepository<T> : IDbSet<T>  where T : class { } public class UnitOfWork : DbContext {        public IRepository<Address> Addresses        {            get;            set;        } } Thanks

  • Anonymous
    July 29, 2010
    Does this not support TimeSpan?  I get the following exception when I have a TimeSpan property. There is no store type corresponding to the conceptual side type 'Edm.Time(Nullable=True,DefaultValue=,Precision=)' of PrimitiveType 'Time'.

  • Anonymous
    July 30, 2010
    @ploeh Currently EF only supports objects with default constructors and properties with getters and setters (with the exception of collection properties, which only need a setter if they aren’t initialized within the object) Having more flexibility in the shape of classes is a common bit of feedback we hear and our team is working on some improvements in this area at the moment. @Flo & @Lukas No definite date for an RTM yet, we’re looking at options to try and support some form of go-live prior to the next full framework release. @Andy Here is the mapping you are after: modelBuilder.Entity<Employee>()    .HasMany(e => e.Territories)    .WithMany(t => t.Employees)    .Map("dbo.EmployeeTerritories", (e, t) => new { EmployeeID = e.Id, TerritoryID = t.Id }); @Ashraf Thoppukadavil I’m not sure exactly what you mean by “a null reference to Author from book”. If you mean that the relationship is nullable then you would use HasOptional in place of HasRequired    builder.Entity<Book>().HasOptional(b => b.Author).WithMany(a => a.Books); If you mean there is no navigation property from Book to Author then you would need to map from Author and use the no-args overload of WithRequired;    builder.Entity<Author>().HasMany(a => a.Books).WithRequired(); @Phil Peace If your types aren’t exposed in either a DBSet<T> or IDbSet<T> then you can register them in the OnModelCreating event. (Or if you are constructing a ModelBuilder externally, as described in this walkthrough, then register them with that ModelBuilder)  public class UnitOfWork : DbContext  {      protected override void OnModelCreating(ModelBuilder modelBuilder)      {          modelBuilder.Entity<Address>();      }    ...  } In your example you would need to initialize the UnitOfWork.Addresses property yourself because DbContext will only initialize DBSet<T> and IDbSet<T> properties by constructing a DbSet<T>. @Steve The error message suggests the database provider you are using doesn’t have a type to store time values in, Microsoft SQL Server supports the use of TimeSpan, are you using a different provider?

  • Anonymous
    August 03, 2010
    Hi, is it possible to use CreateSourceQuery with CodeFirst?  I know that method was on EntitySet<T>, but I was wondering if there is a CodeFirst way to translate ICollection<T> over to EntitySet<T> temporarily for advanced queries. I've also got this asked here, if you need more details. stackoverflow.com/.../using-createsourcequery-in-ctp4-code-first Great work!!!  Love it!!!

  • Anonymous
    August 03, 2010
    Sorry, EntityCollection<T>, not EntitySet<T>

  • Anonymous
    August 04, 2010
    Hi this is great stuff.  It would be great if DbContext could map to existing stored procedures.  Do you have any idea when this may be available?

  • Anonymous
    August 05, 2010
    Hi and many thanks to the EF Team for a great addition to Entity Framework. I'm curious to know if System.Data.Objects.CompiledQuery.Compile() can be used with the new CTP.  The problem, it seems, is that the compile method's first generic parameter must be of type ObjectContext.  Of course, DbContext does expose ObjectContext, but if I argue the exposed context, I can't seem to create a LINQ expression using the ObjectContext which knows about my IQueryable DbSets. Can anyone point me in the right direction here?  I would greatly appreciate it.  BTW, I am able to compile an Expression and cache it as a delegate, but would like to get the speed improvement of a compiled EF Query. Thanks again for an excellent product.

  • Anonymous
    August 08, 2010
    Great walkthru!!!  I can't wait until this stuff is rolled into EF4. Everything worked as expected using Sql Server Express.  However I was only able to get the DbContext example working with Sql Server Compact 4.0 (CE4). Is CE4 supported using the the Object Context?  if so, what changes to code are needed to make it work?

  • Anonymous
    August 10, 2010
    Hi, I was wondering whether or not you will provide support for inheritance. I have the following pocos Product and CleaningProduct derived from Product. I tried creating a context for this scenario but an error pops up saying something about a Discriminator. Any help will be appreciated, Thanks

  • Anonymous
    August 10, 2010
    @Adam It is possible (albeit it a bit complicated) to get a source query, I’ve posted the code on you Stack Overflow thread @Davy Our team originally had a stronger focus on creating new databases with Code First and we are now working to add better support for mapping to existing schemas. Stored procedures are on the list but no definite answer on when they will be supported yet. I expect we’ll have support by the time we RTM. @Mike Compiled queries are not available in CTP4. We’re hoping we can do something more automatic that the existing ObjectContext solution by the time we hit RTM and avoid you having to explicitly compile and cache queries, if this doesn’t get added in time then we will expose a similar option to the existing compiled queries. @Eric ObjectContext does support CE 4.0, the only change you should need to make is to construct a SqlCeConnection rather than a SqlConnection. If this doesn’t work then post up your code and the error you are getting in our pre-release forum and we’ll work through the issue; social.msdn.microsoft.com/.../threads

  • Anonymous
    August 10, 2010
    @Andrei Paun CTP4 supports inheritance, by default we map all types in the hierarchy to a single table and add a column to identify each type. Based on the error you are receiving I suspect you are overriding the default mapping. Here is an example of mapping those two entities to a single table: modelBuilder.Entity<User>()        .MapHierarchy()        .Case<Product>(p => new        {            p.Id,            p.Name,            product_type = "P"        })        .Case<CleaningProduct>(p => new        {            p.CleaningRating,            product_type = "C"        })        .ToTable("Products"); If this doesn’t answer your question then post up your code in our pre-release forum and we’ll help you out; social.msdn.microsoft.com/.../threads

  • Anonymous
    August 10, 2010
    Is it possible for generated table columns to keep the same order as my properties as defined in model classes? If ever the need arises to get down and dirty in SQL, it can be handy to have SELECT * list the primary key first and other logically ordered fields close together. Thanks.

  • Anonymous
    August 11, 2010
    @Georges Bilodeau In CTP4 there isn’t a way to affect the ordering of columns in the database, it is always alphabetical. This is something we plan to improve in future releases so that we have a better default behavior (PK columns first would be part of this) and ultimately give you a way to explicitly define the order. Code First uses reflection to look at class definitions and unfortunately there is no guarantee of consistent ordering of properties returned from the reflection APIs, meaning we don’t have a reliable way to get the order properties were defined in a code file.

  • Anonymous
    August 12, 2010
    Contrary to an earlier blog post (blogs.msdn.com/.../data-annotations-in-the-entity-framework-and-code-first.aspx), using the [Required] annotation attribute on a foreign key navigation property doesn't seem to generate a non-null database column. public class Child {    [Required]    public virtual Parent Parent { get; set; } } The generated table's Parent_Id column is still nullable. Is this a bug? For now, I can begrudgingly get around it by overriding OnModelCreating in my context class and using the fluent API à la: modelBuilder.Entity<Child>().HasRequired(child => child.Parent).WithMany(parent => parent.Children); Having to mix both data annotation attributes and fluent API to fully define columns is undesirable (although possibly unavoidable in certain situations?), not to mention that the RecreateDatabaseIfModelChanges initializer doesn't pick up any changes to the model made outside of the model classes themselves.

  • Anonymous
    August 14, 2010
    @georgesb The required attribute will work on a actual foreign key property but in CTP4 it does not have any effect when put on a navigation property (i.e. if your class included a ParentId property then Code First would correctly interpret this as a required FK). A number of folks have given us this bit of feedback and we will look at adding support for required on navigation properties in the next release.

  • Anonymous
    August 16, 2010
    Any fix to the "dbo" issue when working against a provider different from Sql Server (Ej. postgresql/npgsql)?

  • Anonymous
    August 19, 2010
    @Raul You can use something like modelBuilder.Entity<Employee>().MapSingleType(...).ToTable("public.employee") to get around the dbo issue - worked for me with the latest npgsql library (2.0.10)

  • Anonymous
    August 24, 2010
    The comment has been removed

  • Anonymous
    August 28, 2010
    @Raul Duque You are still limited to the solution Adriaan mentioned, we plan to have a better solution in future releases though. @David Evan We don’t have native support for XML properties yet and no definite plans on when this would be supported.

  • Anonymous
    October 18, 2010
    Is there documentation or unit test that shows all the mappings senories? I have Goggled long and hard but the only information is from blog posts. Is there a way to control the order of the columns created? I like that Id is the first column.

  • Anonymous
    October 19, 2010
    Will DbContext support Translate, and  ExecuteStoreQuery? Itcan be useful when retrieving data from a stored procedure using multiple result sets. Thanks.

  • Anonymous
    October 29, 2010
    Is it possible to have public DbSet<TEntity> Set<TEntity>() where TEntity : class; of DbContext using IDbSet so that it can be mocked?

  • Anonymous
    November 28, 2010
    I've worked through ScottGu's excellent intro to EF CTP4 weblogs.asp.net/.../code-first-development-with-entity-framework-4.aspx but it's left me with a big question... [I'm new to EF4 so apologies if I'm missing something really obvious.] Scott works with 2 classes: Dinner and RSVP. Dinner has a collection of RSVPs (representing the 1:* side of the relationship) and RSVP has an associated Dinner and these are exactly the kind of bi-directional object relationships I'd expect in a rich domain model. What troubles me is that those relationships are also enforced through a PK ID in Dinner and a PK ID and FK DinnerId in RSVP.   From a purely object model POV those IDs are really just database constructs - I might not want to have these IDs exposed in my business model - I might want the database to resolve these for me when I either retrieve a Dinner and it's associated RSVPs or I create a new Dinner with attached RSVPs. I guess my vague architecture concern is that I'm trying to get a handle on how far the EF CTP4 stuff enables the separation of the OM from DB concerns? My more specific developer question is can I make these pesky database IDs private and/or can I roll the ID up into a base class? Thanks. jasonAtWork

  • Anonymous
    February 02, 2011
    Yet again, another case where MS assume everyone use VS2010!

  • Anonymous
    March 04, 2011
    I created a simple template t4 to generate a DbContext class for my model edmx. This template takes the EntitySet as the name of the table. So the pluralization is set in the model.edmx in the property EntitySet (Nombre del conjunto de entidades) You can download my template here: www.mediafire.com/.../Modelo.tt Remember change... string inputFile = @"YourModelFileName.edmx";