Welcome to MSDN Blogs Sign in | Join | Help
Tip 42 – How to create a dynamic model using Code-Only

Background:

When we give examples of how to use Code-Only we always start with a strongly typed Context derived from ObjectContext. This class is used to bootstrap the model.

For example this (property bodies omitted for simplicity sake):

public class MyContext : ObjectContext

   public ObjectSet<Category> Categories { get; }
   public ObjectSet<Product> Products { get; }
}

Tells CodeOnly that to bootstrap a model with 2 EntitySets, a set of Category entities called Categories, and a set of Product entities called Products.

Then if necessary you can further refine the model by manipulating the ContextBuilder.

Problem:

But what if you don’t have a strongly typed Context class?

What if you make a determination at runtime that you need a model, there isn't an appropriate strongly typed Context class lying around.

A customer asked me this very question earlier today.

Solution:

It turns out you can use ObjectContext directly. When you do this though Code-Only knows nothing about the model. But that isn’t that bad all you need to do is explicitly tell Code-Only about all the things it would normally learn from the strongly typed context.

For example this:

public ObjectSet<Person> People { get; }

Can be converted into this:

var builder = new ContextBuilder<ObjectContext>();
builder.RegisterSet<Person>(“People”);

Nifty huh?

End to end example:

This example, persists a Person (BillG) to the database and retrieves it again, all without a strongly typed ObjectContext:

First the Person class (which is POCO):

public class Person
{
    public int ID { get; set; }
    public string Firstname { get; set; }
    public string Surname { get; set; }
}

And now the code to setup the ObjectContext:

// Create the contextbuilder, and tell it about the People set.
var builder = new ContextBuilder<ObjectContext>();
builder.RegisterSet<Person>("People");

// Create a connection
string connstr = @"Data Source=.\SQLEXPRESS;Initial Catalog=PeopleDb;Integrated Security=True;Pooling=False;MultipleActiveResultSets=True";
var conn = new SqlConnection(connstr);

// Create an ObjectContext from the builder
using (ObjectContext ctx = builder.Create(conn))
{
    // Create the database if it doesn’t already exist
    if (!ctx.DatabaseExists())
       ctx.CreateDatabase();

    // Create Bill
    Person p = new Person {
        ID = 1,
        Firstname = "Bill",
        Surname = "Gates"
    };

    // Add Bill to the context
    // UPDATE: thanks to danny for the simplification
    ctx.CreateObjectSet<Person>().AddObject(p);
 using the general purpose
    // AddObject method.
    // The only tricky part is the EntitySet name with must 
    // be qualified with the the container name,  
    // in this case is ObjectContext.
    ctx.AddObject("ObjectContext.People", p);

    ctx.SaveChanges();

    // Issue a query against the People set.
    var bill = (from person in ctx.CreateObjectSet<Person>()
                where person.Firstname == "Bill"
                select person).Single();

    // Make and Save a change.
    bill.Firstname = "William";
    ctx.SaveChanges();
}

Pretty easy considering it isn’t strongly typed.

Posted: Monday, November 09, 2009 4:42 PM by AlexJ

Comments

Daniel Wertheim said:

Hi!

How about an RegisterSet that takes a Type instead of a generic version? Then You could register this dynamically.

I have put up an similar example that could be found:

http://danielwertheim.wordpress.com/2009/11/09/entity-framework-4-ctp-2-clean-code-with-poco-entities/

//Daniel

# November 9, 2009 1:32 PM

Daniel Simmons said:

By the way, if you won't want to figure out the entity set name, you could just change the AddObject line you have above to:

ctx.CreateObjectSet<Person>().AddObject(p);

- Danny

# November 9, 2009 3:01 PM

Kazi Manzur Rashid said:

Just curious, why most of you code snippet uses ObjectSet instead of IObjectSet, the same is true for IList<T> and List<T>. I did a blog post on this issue which you find interesting: http://weblogs.asp.net/rashid/archive/2009/09/13/shrinkr-url-shrinking-service-developed-with-entity-framework-4-0-unity-asp-net-mvc-and-jquery-part-2.aspx

# November 10, 2009 3:24 AM

AlexJ said:

@Kazi,

No real reason, you could obviously do this with IObjectSet and IList etc.

But for this post I wasn't focusing on testability.

Thanks for the link.

Alex

# November 10, 2009 7:41 AM

Daniel Wertheim said:

Hi!

I have now updated my EfEntityStore so that it lets you Auto-register entitymappings and registers the Entitysets etc. You can check it out at: http://daniel.wertheim.se/2009/11/13/entity-framework-4-part-4-autoregister-entitymappings/

//Daniel

# November 13, 2009 4:10 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker