Delen via


Code Only

There are currently two ways to get Entity Framework apps up and running, we call these Database First and Model First respectively.

Database First has been with us since .NET 3.5 SP1, and involves reverse engineering an Entity Data Model from an existing database.

Model First is new to Visual Studio 2010/.NET 4.0 and allows you to create an Entity Data Model from scratch and then generate a database and mapping for it.

However many developers view their Code as their model.

Ideally these developers just want to write some Domain classes and without ever touching a designer or a piece of XML be able to use those classes with the Entity Framework.
Basically they want to write ‘Code Only’.

We are pleased to announce that we’ll be shipping a preview of “Code Only” on top of the .NET Framework 4.0 Beta 1 (more on that in the coming days).

How it works:

To use Code only you simply write some POCO classes, here is a simple example:

public class Category
{
public int ID { get; set; }
public string Name { get; set; }
public List<Product> Products { get; set; }
}

public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
}

Then write a class that derives from ObjectContext that describes the shape of your model and how you want to access your POCO classes, so something like this:

public class MyContext : ObjectContext
{
public MyContext(EntityConnection conn)
: base(conn){ }
public ObjectSet<Category> Categories {
get {
return base.CreateObjectSet<Category>();
}
}
public ObjectSet<Product> Products {
get {
return base.CreateObjectSet<Product>();
}
}
}

NOTE: this persistence / EF aware class could easily be in another assembly so you can keep it separate from your nice pristine domain classes.

At this point you have everything you need from a CLR perspective, but you won’t be able to use the MyContext class without some EF metadata, which is normally stored in the EDMX file.

But remember Code-Only means there isn’t an EDMX file.
So where do we get the metadata?
That is where the ContextBuilder class comes in:

SqlConnection connection = …; // some un-opened SqlConnection
MyContext context = ContextBuilder.Create<MyContext>(connection);

What is happening here is that the ContextBuilder is looking at the Properties on MyContext, inferring a default Conceptual Model, Storage Model and Mapping by convention, it the uses that metadata plus the SqlConnection you passed in to create an EntityConnection, and finally it constructs an instance of MyContext by passing the EntityConnection to the constructor we created previously.

Once you have an instance of your context, we ship several extension methods you can use to automatically create a database script, see if the database exists, drops the database, and/or create the database,. For example this code snippet uses two of those extension methods to create the database if it doesn’t already exist.

if (!context.DatabaseExists())
context.CreateDatabase();

The CreateDatabase call looks at the EF metadata, in particular the Storage Model, aka SSDL, and uses it to produce Database Definition Language (or DDL) which it then executes against against the connection.

Overriding Conventions

In the examples so far everything is done by convention. This is great if you are happy with our conventions. However you may want to override them, for example to register different keys, use different mappings or use a different inheritance strategy etc.

To override the convention instead of creating an ObjectContext directly you create an instance of a ContextBuilder that you can configure.

var contextBuilder = new ContextBuilder<MyContext>();

In the first Feature CTP, Code Only provides the ability to override how the key properties are inferred:

contextBuilder.RegisterKey((Product p) => p.ID);

This code tells the builder that the key of Product is its ID property.

When you’ve finished configuring how you want your model and mappings to work in your code, you create an instance of your context, this time by calling Create on the builder instance you have been configuring:

MyContext context = contextBuilder.Create(connection);

It is that simple.

Over time the features of the ContextBuilder will grow so you will be able to setup custom mappings, mark properties as transient, setup up Facets (e.g. MaxLength), change inheritance strategies, link properties that are the inverse of each other together (e.g. product.Category and category.Products) and more. In fact here is an example of the sort of thing we are aiming to support for the next release of the Feature CTP:

builder[“dbo.prds”] =
from c in builder.OfType<Product>()
select new {
pcode = p.ID,
p.Name,
cat = p.Category.ID
}
);

This snippet:

  • Maps Product entities to the ‘prds’ table.
  • Maps Product.ID to a ‘pcode’ column.
  • Maps Product.Name to a ‘Name’ column.
  • Maps the FK under the Product.Category relationship to the ‘cat’ column.

Here is another example that does basic TPH inheritance:

builder[“dbo.Cars”] = (
from b in builder.OfTypeOnly<Car>()
select new {
id = b.CID.AsKey(),
b.Color,
b.Manufacturer,
disc = “C”
}
).Merge(
from s in builder.OfType<SportsCar>()
select new {
id = s.CID.AsKey(),
s.Color,
s.Manufacturer,
disc = “S”,
hp = s.HorsePower,
tq = s.Torque
}
);

These two examples just scratch the surface of what we are planning on doing, hopefully though they give you a sense of where we are heading.

We are super excited about Code Only. But as of right now our plans to support overriding conventions aren’t finalized, so we’d love to get your feedback, this really is your chance to help us get it right.

Alex James ,
Program Manager, Entity Framework Team, Microsoft

This post is part of the transparent design exercise in the Entity Framework Team. To understand how it works and how your feedback will be used please look at this post .

Comments

  • Anonymous
    June 10, 2009
    PingBack from http://blog.a-foton.ru/index.php/2009/06/11/code-only/

  • Anonymous
    June 10, 2009
    It is always busy here with all the improvements we are doing in Entity Framework to make your code work

  • Anonymous
    June 10, 2009
    Wow! That's stunning! You guy's weren't lying.

  • Anonymous
    June 10, 2009
    What happens when the model changes? How does the database schema get updated?

  • Anonymous
    June 10, 2009
    Thank you for submitting this cool story - Trackback from DotNetShoutout

  • Anonymous
    June 11, 2009
    @Rik, We don't yet have a good story for migrations.  The initial approach assumes that you are using the create database functionality during development and that you will recreate the database each time.  Obviously we would like to support scenarios where we can modify the database schema and preserve data, but we're just not there yet in this release.  Working on it.

  • Danny
  • Anonymous
    June 11, 2009
    What about the following approach -Code First- :
  1. create POCO classes (via VS or UML tools)
  2. generate EDMX -base- Model from (.cs) files
  3. keep those (.cs) files synced with model while adding specific persistance strategies via VS integrated EF designer...etc.. Anyway : "Code Only" is "good news first". I'm waiting for it to pop-up ;-
  • Anonymous
    June 11, 2009
    Daily tech links for .net and related technologies - June 11, 2009 Web Development Opinionated Input

  • Anonymous
    June 11, 2009
    @Didier, We have talked about Code-First too, but if we do it will come after Code-Only. As you can imagine with Code-Only internally the metadata required is being generated, so to do your (2) you just need a mechanism to get the metadata out of memory and on to disk. That should be relatively simple. Part (3) of your suggestion on the other hand is significantly harder because maintaining full fidelity in all transformations between code and model and model and code make things significantly harder. We are not sure that the payoff is sufficient, to deal with that extra complexity. I personally tend to think you get most of the benefits in a world where you do Code-Only, and then decide to go to emit your model / mapping / storage model, (aka EDMX) and use that from now on. I.e. going back from EDMX to the code based modeling and mapping wouldn't be supported.

  • Alex
  • Anonymous
    June 11, 2009
    @Alex, Yes, i agree with you about "is keeping the whole parts synced worth ?" though there will allways be some situation where people would to answer "yes". On the other hand, CodeFirst based on serializing (exporting to EDMX) what is produced "live" by CodeOnly will certainly be VERY usefull : many developpers generate source classes via  UML/MDA tools, maybe tomorrow via VS2010 architecture edition. When can we expect to be able to play with CodeOnly ? -Didier

  • Anonymous
    June 11, 2009
    The comment has been removed

  • Anonymous
    June 12, 2009
    @Didier The first version (for Beta1) is coming soon, I don't know exact dates, but you should think weeks rather than months. @Rik Yes Migrations are something that we keep hearing about again and again, and we agree they are important. While if might be hard to manually do migrations in the EDMX, I suspect it will be a lot easier with code only cause you can modify both ends (database and classes) and make them 'meet' in the middle with a minor change to your mapping configuration code.

  • Alex
  • Anonymous
    June 12, 2009
    Would it be correct to assume that TPT inheritance would work as well?

  • Anonymous
    June 14, 2009
    @Lynn Absolutely. We have worked through design validating that all three major inheritance strategies, TPH, TPT and TPC are supported. Alex

  • Anonymous
    June 16, 2009
    Is the ContextBuilder available in VS2010 beta1?

  • Anonymous
    June 16, 2009
    @Steve No the context builder will ship soon in a Feature CTP that will extend Beta1. Watch out for an announcement soon on the adonet blog. i.e. http://blogs.msdn.com/adonet Alex

  • Anonymous
    June 25, 2009
    Hi, it would be great if we could override conventions from the context also in the next CTP, that is the feature I really need as a framework developer. Please ;-)

  • Anonymous
    June 26, 2009
    @perb, Could you give a little more information?  When you say that you would like to override conventions from the context, do you mean that you want to change the mapping after the context has been created by calling methods on the context rather than on the context builder?  Or are you saying that you want to override conventions about the way the context is put together?  Or are you just saying you want the ability to override conventions? Our current plan is that in the next CTP you will be able to override all conventions when you setup the builder and then create a context that reflects a very fine-tuned mapping story, but you won't be able to change the mapping for a particular context after it has been created.

  • Danny
  • Anonymous
    June 26, 2009
    It's great to see that it will be possible to use model first instead of only database first in the next version of EF. This is a feature that I've wanted from the start. One other thing that I'm wondering though is, say I have a property of List<string> in my class. How will this be handled in EF? I'm using NHibernate now and it gets automatically binary serialized into a BLOB column. Does EF have support for this? I hope that support for this is included in EF.

  • Anonymous
    June 26, 2009
    One other thing that I just remember to ask, does it support ordered lists yet? I asked this awhile back and the answer was that you had to do it manually. What I want to do is do something like have a List<Person> or some other list and have it remember the ordering of the list. i.e. I should not have to manually add another property that holds the index value, it should do that for me automatically behind the scenes. This IMHO is a very important feature that was lacking before. Other ORMs have supported this for years. I really hope that this is included in the next version of EF. If it isn't, that will be a real shame. The same thing goes for lists of primitives like List<string>. There should be a way to map properties to BLOBs and have them transparently serialize/deserialize. I want to switch from NHibernate, but, I'm not doing it until these features are implemented.

  • Anonymous
    June 26, 2009
    @Jon, Sorry but neither lists of primitives nor ordered associations will be supported in EF4.  These are certainly features that can be added, and we'll look to add them in a future release.  They are also things that can be layered on top of the EF without too much trouble in the meantime.

  • Danny
  • Anonymous
    June 29, 2009
    So i tried out this sample code, and quickly realized the only way the builder can build the set information is if the context has properties that return (I)ObjectSet<T>. What would be nice is to generate a generic context which just has methods such as Save<T>, Delete<T>, and Query<T> in which you interact with a set only via the CreateObjectSet<T> method. Will this be supported by EF4 RTM?

  • Anonymous
    June 29, 2009
    @Daniel Simmons I would like to be able to create a context (using the context builder) for one or more POCO classes without having access to the POCO classes at compile time. My prefered approach would be to create the model (from my own metastore) using the context builder, then have callbacks on the created context whenever data from the actual classes has to be read/saved or mapped to the model for LINQ support. With this I can accomplish two goals:

  1. The callbacks would allow me to support properties that are stored in a dictionary on the class but still need to be mapped as ordinary columns. Very useful when building frameworks.
  2. I can provide a context that automatically maps to the database as defined in our store and the developer of our framework does not have to create their own context everytime. They just register their "type" in our store. So, more support for us framework developers that do not have access to the actual classes at compile time.
  • Anonymous
    June 30, 2009
    The comment has been removed

  • Anonymous
    July 01, 2009
    The comment has been removed

  • Anonymous
    July 09, 2009
    This may not be the place to ask, but will the next EF release support server generated keys/Identity columns when using a SQL Server Compact db?

  • Anonymous
    October 13, 2009
    I see there are setters on Collections is there any way to make them private?? And if I'm wanna go for real designing I maybe want to expose IEnumerable<Product> Products and have AddOrder(), RemoveOrder methods how can I achive that? I mean how can I set private fields like private IList<Product> _products; public IEnumerable<Product> Products {     get { return _products; } } Instead of that not uses interfaces at all. public List<Product> Products { get; set; }

  • Anonymous
    June 24, 2010
    This is really great, and I think many of us like to work with objects in code rather than with database tables.  I have a couple of questions:

  1.  Will this work against SQL Azure?
  2.  Is it still possible to map some functions in the opposite direction?  For example, can a view or stored procedure be represented in the EF model even though we did model-first or code-first?