Productivity Improvements for the Entity Framework


Background

We’ve been hearing a lot of good feedback on the recently released update to the Entity Framework in .NET 4. This release marks a significant advancement from the first release that shipped with .NET 3.5 SP1.  I’m not going to spend time here talking about what’s new, but you can check here to see for yourself.

 

With all that said, there are still a number of things we can do to simplify the process of writing data access code with the Entity Framework. 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.  Think of this as a fast path to writing data access code using conventions over configuration, better tuned APIs and other techniques intended to reduce development time when using the EF. 

At this stage we have worked through what we think the core API and functionality should look like and would like your feedback. There are still some capabilities such as data binding and concurrency resolution which will cause the API to evolve as we continue the design process, but the main concepts are in place, so it is a good time for feedback.

 

Introducing DbContext & DbSet

At the heart of the Entity Framework Productivity Improvements are two new types, DbContext and DbSet<TEntity>. DbContext is a simplified alternative to ObjectContext and is the primary object for interacting with a database using a specific model. DbSet<TEntity> is a simplified alternative to ObjectSet<TEntity> and is used to perform CRUD operations against a specific type from the model. These new types can be used regardless of whether you created your model using the Entity Designer or code.

 

 

The obvious question is ‘Why not just simplify ObjectContext and ObjectSet<T>?’  We are opting to introduce these new types in order to, on the one hand, preserve full backward compatibility with existing EF applications and continue to address all of the advanced scenarios that are possible given the EF’s existing flexibility, while on the other hand streamlining the experience of using the EF and tuning it for the most common cases.  We believe it is critical that the EF programming experience improve in some fundamental ways, and at the same time we are absolutely committed to our existing customers.  Establishing a collaborative relationship between the existing types and the new types allows us to achieve both requirements.  Also, there are easy ways to get to ObjectContext and ObjectSet<T> from DbContext and DbSet in case you want more control for a particular task.

One point we want to be very clear about is that these new types are not replacing any existing types; they are a simplified alternative that build on the existing types, and as we add features to the Entity Framework they will always be available in ObjectContext/ObjectSet, and they will also be available in DbContext/DbSet if appropriate.

 

We’ll drill into the API surface later, but first let’s take a look at the coding experience using these new types.

Code First Experience

DbContext provides a simplified Code First pattern that requires less code and takes care of some common concerns such as model caching, database provisioning, schema creation and connection management. This simplified pattern uses a number of conventions to take care of these tasks and allows tweaking or overriding of this behavior when required. Let’s start off by using these conventions to write the code needed to build a console application that performs data access using a model:

A Visual Basic version of these code samples is available here.


using
System.Collections.Generic;

using System.Data.Entity;

 

namespace MyDataAccessDemo

{

    class Program

    {

        static void Main(string[] args)

        {

            using (var context = new ProductContext())

            {

                var food = new Category { CategoryId = “FOOD” };

                context.Categories.Add(food);

 

                var cheese = new Product { Name = “Cheese” };

                cheese.Category = context.Categories.Find(“FOOD”);

                context.Products.Add(cheese);

 

                context.SaveChanges();

            }

        }

    }

 

    public class ProductContext : DbContext

    {

        public DbSet<Product> Products { get; set; }

        public DbSet<Category> Categories { get; set; }

    }

 

    public class Product

    {

        public int ProductId { get; set; }

        public string Name { get; set; }

        public Category Category { get; set; }

    }

 

    public class Category

    {

        public string CategoryId { get; set; }

        public string Name { get; set; }

        public ICollection<Product> Products { get; set; }

    }

}

 

That is 100% of the code you would write to get this program running. No separate model definition, XML metadata, config file or anything else is required. Conventions are used to fill in all of this information. Obviously there is quite a bit going on under the covers so let’s take a closer look at some of the things DbContext is doing automatically.

Model Discovery

During construction we scan the derived context for DbSet properties and include the types in the model. Model Discovery uses the existing Code First functionality so the new default conventions we recently blogged about are processed during discovery. You can opt out of set discovery by specifying an attribute on the set properties that should be ignored.

 

 

Of course there will be times when you want to further describe a model or change what was detected by convention. For example say you have a Book entity whose ISBN property is the primary key, this won’t be detected by convention. There are two options here; you can use data annotations to annotate the property in your class definition:

public class Book

{

    [Key]

    public string ISBN { get; set; }

    public string Title { get; set; }

}

 

Alternatively DbContext includes a virtual method that can be overridden to use the Code First fluent API on ModelBuilder to further configure the model:

public class ProductContext : DbContext

{

    public DbSet<Book> Books { get; set; }

 

    protected override void OnModelCreating(ModelBuilder modelBuilder)

    {

        modelBuilder.Entity<Book>().HasKey(b => b.ISBN);

    }

}

Model Caching

There is some cost involved in discovering the model, processing Data Annotations and applying fluent API configuration. To avoid incurring this cost every time a derived DbContext is instantiated the model is cached during the first initialization. The cached model is then re-used each time the same derived context is constructed in the same AppDomain. Model caching can be turned off by setting the CacheForContextType property on ModelBuilder to ‘false’ in the OnModelCreating method.

DbSet Initialization

You’ll notice in the sample that we didn’t assign a value to either of the DbSet properties on the derived context. During construction DbContext will scan the derived context for DbSet properties and, if they expose a public setter, will construct a new DbSet and assign it to the property. You can opt out of set initialization by specifying an attribute on the set properties that should not be initialized.

You can also create DbSet instances using the DbContext.Set<TEntity>() method if you don’t want to expose public setters for the DbSet properties.

Database Provisioning

By default the database is created and provisioned using SqlClient against localhost\SQLEXPRESS and has the same name as the derived context. This convention is configurable and is controlled by an AppDomain setting that can be tweaked or replaced. You can tweak the default SqlClient convention to connect to a different database, replace it with a SqlCe convention that we include or define your own convention by implementing the IDbConnectionFactory interface.

 

public interface IDbConnectionFactory

{

    DbConnection CreateConnection(string databaseName);

}

 

The active IDbConnectionFactory can be retrieved or set via the static property, Database.DefaultConnectionFactory.

 

DbContext also includes a constructor that accepts a string to control the value that is passed to the convention, the SqlClient and SqlCE factories allow you to specify either a database name or the entire connection string.

Before calling the convention, DbContext will check in the app/web.config file for a connection string with the same name as your context (or the string value if you used the constructor that specifies a string). If there is a matching entry, we will use that rather than calling the convention. Because connection string entries also include provider information this allows you to target multiple providers in one application.

Finally, if you want full control over your connections there is a constructor on DbContext that accepts a DbConnection.

Database First and Model First Experience

In the latest version of the Entity Framework that shipped with .Net Framework 4.0 and Visual Studio 2010 we introduced T4 based code generation. T4 allows you to customize the code that is generated based on a model you have defined using the designer in either the Database First or Model First approach. The default template generates a derived ObjectContext with an ObjectSet<T> for each entity set in your model.

The productivity improvements will also include a template that generates a derived DbContext with a DbSet<TEntity> for each entity set in your model. This allows Model First and Database First developers to make use of the simplified API surface described in the next section.

API Surface

DbContext is the starting point for interacting with your model. Compared to ObjectContext it has a greatly reduced number of methods and properties that are exposed at the root level. The aim is to expose only the most commonly used methods on DbContext and have the ability to drill down to more advanced APIs. One example of this is the Database property that exposes database related APIs. We will add a couple more members as we work through adding the rest of the advanced functionality but we want to keep it as minimal as possible. In most cases you would work with a context that derives from DbContext and exposes strongly typed DbSet properties for the types in your model.

public class DbContext : IDisposable

{

    public DbContext(DbModel model, string nameOrConnectionString);

    public DbContext(DbModel model, DbConnection existingConnection);
    public DbContext(ObjectContext objectContext);

 

    protected DbContext();

    protected DbContext(string nameOrConnectionString);

    protected DbContext(DbConnection existingConnection);

 

    public Database Database { get; }

    protected ObjectContext ObjectContext { get; }

   

    protected virtual void OnModelCreating(ModelBuilder modelBuilder);

    public virtual int SaveChanges();

    public DbSet<TEntity> Set<TEntity>() where TEntity : class;

    public void Dispose();

}

 

DbModel Constructors

These constructors can be used with Database First, Model First and Code First development. They are used by our T4 template for Database First and Model First Development and can also be used in Code First scenarios where a model is built externally using ModelBuilder.

Code First previously contained a ContextBuilder type which we have now split into two components, ModelBuilder and DbModel. ModelBuilder is mutable and exposes the fluent API for defining your model. ModelBuilder creates an immutable DbModel type that can be used to construct an ObjectContext or DbContext. DbModel can also be constructed from a Database First or Model First approach where an edmx file is generated.

ObjectContext Constructor

If you have an existing code base that uses ObjectContext and want to make use of the alternate surface of DbContext in some parts of your code then this constructor allows you to wrap the ObjectContext with the simpler surface.

Protected Constructors

The three protected constructors can be exposed or used within a derived context where you want to make use of the simplified Code First experience which was explained in the ‘Code First Experience’ section. They are protected because the model discovery, database provisioning and model caching mechanisms rely on having a derived context.

Database

The Database property exposes an instance of the new Database type that contains methods for interacting with the underlying database.

public class Database

{

    public DbConnection Connection { get; }

 

    public void Create ();

 

    public bool CreateIfNotExists();

 

    public bool Exists();

    public static bool Exists(string nameOrConnectionString);

    public static bool Exists(DbConnection existingConnection);

 

    public void Delete ();

    public static void Delete (string nameOrConnectionString);

    public static void Delete (DbConnection existingConnection);

 

    public bool DeleteIfExists();

    public static bool DeleteIfExists(string nameOrConnectionString);

    public static bool DeleteIfExists(DbConnection existingConnection);

}

 

ObjectContext

DbContext uses an ObjectContext internally and we make this available as a protected property just in case you ever need to drop down to the lower level API. You can use or expose the required functionality from a derived DbContext.

OnModelCreating

This protected member can be overridden when defining a derived context in CodeFirst development and allows you tweak the shape of your model that was detected by convention.

SaveChanges

This method exposes the same functionality as SaveChanges on ObjectContext and persists all pending changes to the database. It represents the Unit of Work for the context.

Set<TEntity>

This method will create a DbSet<TEntity> for an entity type that is part of your model, similar to CreateObjectSet<T> on ObjectContext.

DbSet represents a collection of a given entity type in your model, similar to ObjectSet<T> except that this new type also supports derived types whereas ObjectSet<T> only supported base types.

public class DbSet<TEntity> : IDbSet<TEntity>, IQueryable<TEntity> where TEntity : class

{

    public void Add(TEntity entity);

    public void Remove(TEntity entity);

    public void Attach(TEntity entity);

    public TEntity Find(params object[] keyValues);

}

 

Add, Remove & Attach

Add, Remove and Attach are similar to AddObject, DeleteObject and Attach on ObjectSet<T>. We’ve renamed Add and Remove to keep DbSet<TEntity> consistent with other sets in the framework.

Add and Attach can now be called on objects that are already tracked by the context, Add will ensure the object is in the added state and Attach the unchanged state. This is helpful in N-Tier and Web scenarios where you have a detached graph containing both existing and new entities that need to be hooked up to the context.

For example assume you have a new product that is linked to an existing category, neither instance is attached to a context (they may have been returned from a distributed client via a web service call or built from a post back in a web application). Because Add and Attach are graph operations, calling Add on the product will also Add the category. Previously you would need to drop down to lower level APIs (ObjectStateManager.ChangeObjectState) to mark the category as unchanged. Now however this can be achieved by calling Attach:

public void AddProduct(Product product)

{

    using (var context = new ProductContext())

    {

        context.Products.Add(product);

        context.Categories.Attach(product.Category);

        context.SaveChanges();

    }

}

 

Find

The new Find method will locate an object with the supplied primary key value(s). Find initially checks the in-memory objects before querying the database and is capable of finding added entities that haven’t been persisted to the store yet. If find doesn’t locate an entity with the matching key it returns null.

IDbSet<TEntity>

DbSet<TEntity> implements IDbSet<TEntity> to facilitate building testable applications.

public interface IDbSet<TEntity> : IQueryable<TEntity> where TEntity : class

{

    void Add(TEntity entity);

    void Attach(TEntity entity);

    void Remove(TEntity entity);

    TEntity Find(params object[] keyValues);

}

 

IDbSet<TEntity> allows you to define an interface that can be implemented by your derived context, similar to the example shown below. This allows the context to be replaced with an in-memory test double for testing. DbContext will still perform set discovery and initialization, described in the ‘Code First Development’ section, for properties typed as IDbSet<TEntity>.

public interface IProductContext

{

    IDbSet<Product> Products { get; }

    IDbSet<Category> Categories { get; }

}

 

public class ProductContext : DbContext, IProductContext

{

    public IDbSet<Product> Products { get; set; }

    public IDbSet<Category> Categories { get; set; }

}

Summary

These improvements are designed to provide a cleaner and simpler API surface that allows you to achieve common scenarios with ease while also allowing you to drill down to more advanced functionality when required. The improvements build on top of the existing Entity Framework components using conventions over configuration and a simplified API surface.

We’d like to hear any feedback you have on the proposed functionality and API surface.

Rowan Miller
Program Manager
ADO.NET Entity Framework Team

Comments (51)

  1. S C says:

    Great, we are assuming that the DBContext can be used by RIA services. When will this be available?

  2. Sean says:

    Looking very nice!

    Will there be a refresh of the SqlCe provider at some point so we can create databases and use identity columns? Or will this have to wait until EF vNext?

  3. Taylor says:

    So glad to hear from the EF team but I was hoping instead of productivity improvements you would be announcing performance improvements. In particular I hoped for improvements using TPT inheritance and improvements using .Include().  Explicit loading of related entities (when I don't even want my original query to be attached to the context) and 100+ column tables (after migrating to TPH) makes me a little sad – and I am still worried about scalability.  In some places I have to abandon inheritance altogether in favour of composition.

    I am into EF for the long term and I don't expect progress to evolve on my requirements alone, but I would like some reassurance I am backing the right team.  

    (Architecture: SQL Server -> EF STE Template, BL, WCF -> ASP.NET Web Forms -> Browser)

  4. David says:

    Hi, im glad for all the improvements that this version of Entity Framework has. I really expect that this technology will mature over the next years.

    However there a couple of matters that this framework should enhance too. Actually im working in a ASP.NET MVC app that uses patterns like Repository for data access with lazy loading enable, it has been a pain to work with lazy loading because my business entities have to be instantiated by the Object context. If we don’t use lazy loading then when we need to have some child properties load, it’s necessary to explicitly tell the ObjectContext to load those properties, which is trouble for us too.

    After work with EF a couple of months I can tell that this technology is not totally “disconnected” or “persistence ignorance” there are a few dependencies that should be removed.

    EF leads to  serious architecture concerns, sure there are workarounds  but I don’t think Entity Framework is helping to build better architectures, I think EF is focusing in given productivity to .NET developers but with a high cost.

    I  really appreciate EF teams  efforts to deliver a good product to developers, still have hope that this technology will soon get better.

  5. Taylor says:

    My previous comment may have been too harsh on the EF team.  I love EF really.  I recognise that under other scenarios the objectcontext would live longer and this would offer performance benefits.  Perhaps I could then benefit from design-time view generation, etc.  It may just be my scenario that is so demanding.

    Do you think the disconnected web world is sometimes a second thought for the EF team?  Perhaps it is my fault for getting aboard too early and maybe there are lots of goodies for me in the EF roadmap.

    Taylor

  6. Mark says:

    What namespace contains DbContext and DbSet?

  7. lynn eriksen says:

    Rowan, you mention SQL Express and CE along with the DbConnection. Two questions:

    1) Code-only will be able to be supported by third-party drivers correct?

    2) Could you provide an more comprehensive example of how you might set up a DbContext object with custom connection string?

  8. Serioga says:

    Rowan, what about Detach method? Why Attach only?

  9. Rowan Miller says:

    @S C

    We have just finished working through the core functionality for the improvements and are looking at how they integrate with other technologies, we’ll provide more details as we work through this. RIA services integration is definitely something we are looking at.

    We’re hoping to get a preview of this new work out in the near future so that people can use it and provide feedback. The RTM for this work will most likely be in the next full release of EF.

    @Sean

    Yes we are working on an updated CE provider at the moment that supports identity columns and database creation. This will release independently of EF vNext.

    @Taylor

    Thank you for the feedback, scalability and performance are areas our team is actively working on at the same time as the productivity work, you’ll likely see design blog posts around these efforts in the future.

    We certainly had a gap in disconnected scenarios in EF v1. In the last release we added a number of features to support these scenarios including, as you mentioned, Self Tracked Entities.

    @David

    Patterns for MVC is an area we are spending time as part of these productivity improvements, I’d be interested to follow up on with you on your particular scenario and how we could address it.

    If you want to email me then we can talk through the scenario in more detail; rowmil ‘at’ microsoft ‘dot’ com.

    @Mark

    We are looking at using the System.Data.Entity namespace (which is currently unused), although this isn’t set in stone yet.

    Some of the types that you don’t need to directly use all that often (like IDbConnectionFactory) would live in a subnamespace.

    @lynn eriksen

    1) Yes, the provider changes to support database creation (used by Code First) were included in EF4 so it is already available for third parties to implement

    2) There are two options for specifying a connection string

    You can add a connection string to your app/web.config file that has the same name as your context:

       <connectionStrings>

           <add name="ProductContext" connectionString="Server=MyServer;Database=MyDatabase;Trusted_Connection=true" providerName="System.Data.SqlClient" />

       </connectionStrings>

    If it is a Microsoft SQL Server connection then you can pass this to the constructor of your context

    (This is taken care of by our default IDbConnectionFactory implementation, the CE factory we plan to ship would also support passing a connection string)

    – You need to expose the string constructor on your derived context:

       public class ProductContext : DbContext

       {

           public ProductContext(string nameOrConnectionString)

               : base(nameOrConnectionString)

           { }

           …

       }

    – Then just pass the connection string in when you construct the context

       var context = new ProductContext("Server=MyServer;Database=MyDatabase;Trusted_Connection=true");

    ~Rowan

  10. Felipe Fujiy says:

    "Previously you would need to drop down to lower level APIs (ObjectStateManager.ChangeObjectState) to mark the category as unchanged. Now however this can be achieved by calling Attach:"

    This happen always at EF4 or just when using DbContext?

  11. Sean says:

    Thanks Rowan. So, will there be a Go Live version of these bits before the next EF release, and is the next EF going to be at the same time as the next .NET? Just trying to get a feel 🙂

  12. Rowan Miller says:

    @Serioga

    We considered including Detach and are still open to the idea based on feedback. I’d be interested to hear if there are common scenarios where you would want to use Detach?

    @Felipe Fujiy

    This consolidated behavior of Add/Attach will just be on DbContext/DbSet.

    @Sean

    We want to make sure we get enough community feedback before we consider a go-live, our focus at the moment is making sure we get the API surface right. I anticipate we will do a couple of previews of this work and then depending on timing and feedback we may consider a go-live prior to the next release of the framework, we don’t have definite plans either way at the moment. Yes current plan is to release the next version of EF as part of the .NET Framework.

  13. Matt says:

    No constructive feedback from me at this time – only want to say that everything I've read here looks great! I've just started using EF4 and will definitely appreciate the productivity improvements!

  14. Felipe Fujiy says:

    Rowan Miller,

    When I do this: person.Cars.Count(). EF4 select all Cars for that person from database and then Count at .Net. NHibernate 3 is working at this case, with Extra-Laziness.

    You have any plan to do this queries at Database with a Count(), Max(), etc?

    Another scenario: person.Cars.Add() load all Cars for that person too.

  15. JasonBSteele says:

    Presumably with the Database First scenario we can update the DbSets from the database when new columns are added. I believe there was a previous post which discussed alternative solutions to how to enable code generation but prevent it from overwriting code. Are we likely to see any solution to this in the code generation for DbSets… or will we need to continue to put our business logic in a separate partial class?

  16. Rowan Miller says:

    @JasonBSteele

    You would need to continue using partial classes or opt out of code generation and maintain your own classes. There is also a middle ground where you can take control of the T4 template that generates the code and either include your business logic (if it can be expressed in a generic way) or remove parts of the generation that you want to maintain yourself.

  17. lynn eriksen says:

    An 'out-of-band' release would be very helpful. 2-4 years is a long time to wait for these updates.

  18. Sean Kearon says:

    This really is very elegant code indeed.  I can't wait to be able to start using it.  Can someone clarify if this is available in the current release or is this a future scenario?

  19. Rowan Miller says:

    @Sean Kearon

    This is a future scenario, we are working on a CTP of these new features that we should have out shortly.

  20. Sean Kearon says:

    @Rowan – thanks for the response.  I'm really looking forward to being able to try these features out.  This is the most exciting looking ORM code I have seen in my many years of using ORMs!  Can't wait…

  21. vasek7 says:

    Shortly? Can you be more specific? One week, one month, half a year…? I'm so exited by this technology.

  22. Ross says:

    Are there any plans to include database "evolution" in Entity Framework? So that when changes are made to the model, the framework will generate a sql script to update the database with the model changes?

  23. shawn says:

    I have to agree with Felipe, it would be *great* if we could query on entity relationships without having to materialize the full set first, for example:

    category.Products.Count();

    or

    category.Products.Where(o => o.OnSale);

  24. Rowan Miller says:

    @Ross

    Schema migration is something we are currently looking at, we aren’t settled on what we are going to do in this space but we know we need to provide some solution.

    Once we’ve worked through the options we’ll post up a design blog post to share the direction we are planning to head to get feedback.

  25. Rowan Miller says:

    @shawn & @Felipe Fujiy

    This is great feedback, there are other items higher on the priority list (like enum support 🙂 ) but being smarter about when we lazy load a collection is something we will look at.

    The category.Products.Where(o => o.OnSale); scenario is actually quite interesting because you would presumably want it to also return any new Products that are OnSale but haven’t been saved to the store yet. It could issue a query to the database to bring all the OnSale products in to memory and then use LINQ to Objects to find the added ones, this gets messy when the store query has slightly different rules than LINQ to Objects (i.e. String.Contains() is case sensitive but for MS SQL Server the equivalent LIKE operator is case insensitive). Things like Count() are a lot easier.

  26. Axel says:

    Love it. Looking very good already. Make sure you support N:M relationships directly (i.e. public ICollection<Category> Categories { get; set; } in the Product class from the sample), and generate the underlying intersect table transparently, if not already done. This *starts* to look like an OODB and I could not be happier (have used ObjectStore in 1988…).

    What would be great is auto-schema migration, at least cover simple cases like adding properties (nullable and/or default value in attributes?), removing properties, changing data types, size or precision, with some hook for more complex cases.

    Does the System.ComponentModel.DataAnnotations stuff works on persitent classes properties (Required, StringLength, RegularExpression…)?

    Is there a way to specify indexes, like [Indexed] at the property level, or [Index(compound_index_description)] at the class level?

    A product called DataObjects.NET 3.9.5 tried to do all of the above with some success.

    Last, but  oe teast, does is works 100% on SQL Azure?

    Thanks!

  27. Matthew Wills says:

    @Felipe Fujiy,

    Use person.Cars.CreateSourceQuery().Count() to avoid pulling down all the Cars rows over the wire.

  28. Rowan Miller says:

    @Axel

    Thanks for the Feedback!

    We do support the many to many with a join table created under the covers, this is in the CTP we just release; blogs.msdn.com/…/CTP4Announcement.aspx

    Schema migration is something we are looking at currently, we aren’t sure exactly which direction we will head but we know we need a better story than we currently have (i.e. drop and re-create)

    Yes we support annotations on class properties, the complete list we plan to support is described in this post; blogs.msdn.com/…/data-annotations-in-the-entity-framework-and-code-first.aspx. RegularExpression isn’t supported currently.

    There isn’t native support for adding indexes, although we are getting a lot of asks for this so we may support it in the future. You can run some custom logic during database initialization to do this manually by creating a custom IDatabaseInitializer for your derived context and setting in with System.Data.Entity.Infrastructure.Database.SetInitializer<TContext>().

    In the current CTP there are some issue with database creation against Azure but these will be ironed out in the next release.

  29. Ross says:

    Thanks Rowan. Exciting things to look forward to! Can't wait to see the post about schema migration ideas.

  30. Angelo Daguil says:

    I was getting "The provider did not return a ProviderManifestToken string" in my project.   I'm trying to connect to my SQL Server 2008. This error occurred when I added connection string in my app.config file.Can you help me what is this error all about?

  31. Scott Prugh says:

    It isn't clear if all the mappings can be dynamically overidden in the OnModelCreating.

    I can definitely do this:

    modelBuilder.Entity<Product>().MapSingleType().ToTable("tbl_product");

    But how would I dynamically discover all entities and rename them on the fly.  We have database standards that have been in place for years and I would like to have a base class that discovers all entities and standardizes table and column naming dynamically.

  32. Rowan Miller says:

    @Angelo Daguil

    Could you post in our pre-release forum and include the connection string entry that you have added to app.config so that we can work out what is going wrong for you; social.msdn.microsoft.com/…/threads

    We do support access to SQL Server 2008 using the System.Data.SqlClient provider

    @Scott Prugh

    Anything that is detected by convention can be overridden in OnModelCreating

    There isn’t a good way to generically perform configuration in CTP4, we are looking at allowing custom conventions to be registered in the future.

    That said you can use some VERY hacky code to get at the internals of ModelBuilder to generically rename tables in CTP4, this is obviously something we will improve on in the next release:

       foreach (var item in modelBuilder.Configurations)

       {

           var getTypeMethod = item.GetType().GetMethod("GetConfigurationType", BindingFlags.NonPublic | BindingFlags.Instance);

           var entityType = (Type)getTypeMethod.Invoke(item, null);

           var tableName = "tbl_" + entityType.Name.ToLower();

           ((dynamic)item).MapSingleType().ToTable(tableName);

       }

  33. Alexey says:

    When will enumerations and 2nd level cache be supported?

  34. Rowan Miller says:

    @Alexey

    We don’t have any definite details on releases etc. but these are both features our team is working on.

  35. jmahoney says:

    Question on Code First and Configurations.  The Property.IsRequired() is available on strings but not int/long types.  Intentional?  Does that need to be enforced with a DataAnnotation?

  36. Rowan Miller says:

    @John@

    This is intentional, because int/long/etc can’t physically be assigned null in the CLR Code First assumes they are required.

  37. Todd Morrison says:

    Has anyone noticed that Object does not serialize an object graph?

    context.saveChanges() returns 1, but on retrieve Object properties are null.

    Just tried this with a Guid

  38. Todd Morrison says:

    Another Observation.

    When seeding dynamic DB Filename for SQL CE in MSTest, async is out.

    This is because something like

    Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0", dynamicName+ ".sdf", "");

    clobbers dbcontexts on other threads.

    This can totally be done via Dependency Inject, but I could see other scenarios where I want the connection details on the dbContext to be stateful.

    Any thoughts?

  39. Todd Morrison says:

    @John, have you tried not on the Object Long/Integer, not the primitive?

  40. Todd Morrison says:

    The next big question:

    How do I inject custom DBConnection into the dbContext initialization?

    Example:

    Custom dbContext TedsEntityContext for entities with constructor accepting dbConnection (for dynamic creation).

    calling

    Database.SetInitializer<TedsEntityContext>(new AlwaysRecreateDatabase<TedsEntityContext>());

    loads the type with default constructor, which grabs the dbConnection from the Database.DefaultConnectionFactory.

  41. Todd Morrison says:

    Further Developments…

    Looks like the easy, simple way of doing this is

    SqlCeConnectionFactory("System.Data.SqlServerCe.4.0",

                   this.TestContext.TestDeploymentDir, "Data Source=|DataDirectory|" + dbName +".sdf");

    This works like a charm is and is async safe!

    Sorry for the 4 posts that could have been consolidated after a nights work.

  42. Rowan Miller says:

    @Todd

    I’m not quite sure what you mean by your first comment, if you could start up a thread in our pre-release forum with the code that isn’t working as expected that would be great; social.msdn.microsoft.com/…/threads

    The default connection factory is an AppDomain wide convention that is used for all contexts so you shouldn’t include any context specific settings in there. DbContext includes constructors that allow you to specify the database name or an existing DbConnection, these are covered in more detail in this post; blogs.msdn.com/…/ef-feature-ctp4-dbcontext-and-databases.aspx

    The database initializers will use whichever connection is used to construct the first instance of your context, so if you pass an existing DbConnection then this same connection will be used inside the initializer (the initializers don’t actually call a constructor on your derived context, we use the same context you construct but swap out a bunch of the internals so that it looks and behaves like a separate instance during initialization).  

  43. Telison says:

    I have created a nice DbContext with all my DBSets. Now a situation has come up where I want to do something like query.MergeOption = MergeOption.NoTracking. The reason is that I need a detached object graph.

    MergeOption obviousy is a property on the ObjectQuery class. I cannot come up with a way to accomplish this in the "new world". So any suggestions on how I could accomplish this? I'm fine with either getting a hold of an and underlying ObjectQuery (if there is one) from my DbContext/DbSets or any suggestions on an alternative way to get the detached graph.

  44. RiaGuy says:

    Is there a way to override db schema, so I could use for example Membership.User instead of dbo.User table name?

  45. Rowan Miller says:

    @Telison

    The underlying ObjectContext is a protected member on DbContext so you could define something like this on your derived DbContext:

     public IQueryable<Blog> NoTrackingBlogs()

     {

         var blogs = base.ObjectContext.CreateObjectSet<Blog>();

         blogs.MergeOption = MergeOption.NoTracking;

         return blogs;

     }

    @RiaGuy

    There is a protected OnModelCreating method you can override on DbContext to tweak the schema using the Code First Fluent API, the call you are after is: modelBuilder.Entity<User>().MapSingleType().ToTable(“Membership.User”)

    In the next release you will also be able to do this with a [TableName(“Membership.User”)] attribute on your class.

    There is more information on mapping to an existing database here; romiller.com/…/ef-ctp4-tips-tricks-mapping-to-an-existing-database

  46. Jenda@Krynicky.cz says:

    The support for views in database first is … very, very bad.

    If I am lucky, the Update from database wizard does import the view marking all columns as part of the key and adds a "warning" that it could not infer the proper key columns. Even though I've already edited the file and did mark the key columns and the view did not change. OK, no big deal, I already have an extension that preserves the primary keys for views.

    If I'm not lucky, I get a "warning 6013: The table/view '…' does not have a primary key defined and no valid primary key could be inferred." instead of "warning 6002: The table/view '…' does not have a primary key defined. The key has been inferred and the definition was created as a read-only table/view.", the entity is commented out in store and there is no EntitySet in Store, no mapping and nothing in Concept. Even though the first time the view was imported with just 6002 and the key and everything is in the old .edmx.

    Someone screwed up.

    Not speaking of the fact that if I add an association via the Designer it will not let me specify the columns to use (but rather randomly choose whether to select some columns or create new ones) and it will not propagate the association to Store. Again I can take care of both in an extension and except for NtoN associations I already did, but thanks to the random 6013 in place of 6002 this is not reliable either.

    THANK YOU VERY MUCH!

  47. Alex says:

    I have no found any way to abort neither EF Query nor SaveChanges(). If user creates heavy filter against million records table Query may hangs for a very long time. Very strange that even EntityCommand.Cancel(), described in msdn as a way to cancel operations, has empty implementation in EF 3.5.1 and 4.0!

  48. John@elmsoftware.com says:

    Our program will use SQL Azure or SQL CE as the database, dependent on the clients needs.

    When using EF against SQL Azure, I need the ability to specify a schema.

    When using EF against SQL CE, I need the ability to specify no schema.

    Each schema, will have the same table structures for each unique customer.

    My program just needs to specify the schema.

    I hope that is in the next update to EF.

  49. Rowan Miller says:

    @Jenda, @Krynicky.cz @Alex & @John@elmsoftware.com

    This is all great feedback thank you, we also have a user voice site where you can suggest and vote on features; data.uservoice.com/…/72025-ado-net-entity-framework-ef-feature-suggestions

  50. Peter Crabtree says:

    >  Also, there are easy ways to get to ObjectContext and ObjectSet<T> from DbContext and DbSet in case you want more control for a particular task.

    Pardon my ignorance, but… There are? How?