Entity Framework ObjectContext

February 21, 2009

IntroductionWeb Development

It’s been a good two months since the last post. Today I finally found some spare time to write a new article about .NET. This will be the first article on this blog focusing solely on the Entity Framework. More in particular about using the Entity Framework in different environments such as Windows Applications and in an ASP.NET environment.

The Entity Framework has some drawbacks that will hopefully be addressed in the second release, but in its current state it’s already a really useful technology to use for database access.

This article will not discuss every feature of the Entity Framework as that would entail writing an entire book. The primary focus is on how to deal with the ObjectContext in different environments such as a regular Windows Application and a Web Application (ASP.NET). Let’s get started…

Table Of Contents

ObjectContext

As you may be aware every object returned by a query (Linq To Entities, Entities SQL…) is automatically attached to an object context. This context tracks the changes applied to these objects so that it can later figure out how to persist these changes to the underlying data store.

This object context is represented by a class fittingly named ObjectContext. The ObjectContext encapsulates a couple of things, namely:

  • The connection to the underlying data store (database)
  • Metadata describing the Entity Data Model (EDM)
  • An ObjectStateManager for tracking changes to the objects

As you will see in the next sections how you deal with the ObjectContext depends on the target platform of your application.

Top of page

Demo Solution

Let’s quickly setup up a demo project that we can use throughout the rest of this text. First let us create a simple database using SQL Server consisting out of two tables [Customer] and [Order].

The following two figures list the columns for each of these tables. You can find the DDL statements to build this database in the source code accompagnying this article.

I’ve called my database “Westwind” but feel free to choose a more appropriate name.

Figure 1 – Customer table
Customer Table

Figure 2 – Order table
Order table

The [Order] table contains a foreign key connecting it’s CustomerId column to the Id column of the [Customer] table. Thanks to this relation we can easily navigate back and forth between the Customer and Order entities in the resulting Entity Data Model (EDM).

Now fire up Visual Studio 2008 and create a new blank solution named “ObjectContext” and add a class library to it (C#) titled “DAL” (short for Data Access Layer). Delete the automatically generated class Class1 and add a new ADO.NET Entity Data Model called “Westwind.edmx”.

Using the resulting wizard choose the option “Generate from database” to let Visual Studio generate an Entity Data Model based upon the previously created database. After the model is generated the necessary references to the required assemblies are automatically added to the project.

Figure 3 – ObjectContext Solution
ObjectContext Solution

The Entity Data Model contains two entities, namely Customer and Order. I’ve renamed the Entity Set Name properties of the Customer and Order entities respectively to Customers and Orders. As a last step the navigation property Order on the Customer entity has been renamed to Orders as a customer can have one or more orders.

Figure 4 – Westwind Entities
Westwind Entities

Voila, that concludes setting up the demo project. Let’s move on to the next section…

Remarks

  • Be sure you have the first service pack installed for both the .NET Framework 3.5 and Visual Studio 2008 as both are required in order to be able to work with the Entity Framework.
  • The example is kept as simple as possible in order to focus solely on the subject of this article. It’s not a guideline on how to organize your projects into different layers and such.

Top of page

Windows Application

I’ve added some dummy data to the table using SQL Server Management Studio Express. There are three customer and each has exactly one order.

Figure 5 – Customer Data
Customer Data

Figure 6 – Order Data
Order Data

Regular Windows Applications (Console, WinForms, WPF…) are the easiest to work with in regard to handling the ObjectContext. Let’s demonstrate this using a Console application.

Add a new Console application and add a reference to the DAL project and the System.Data.Entity assembly. Next add an application configuration file (App.config) and copy the connection string found in the App.config file of the DAL project. Finally add the code of Listing 1 to the main method.

Listing 1 – ObjectContext in a Console application

using (var context = new WestwindEntities())
{
    // Query all the orders.
    var q = from o in context.Orders.Include("Customer") orderby o.Total select o;
    foreach(var order in q)
    {
        Console.WriteLine(String.Format("{0} {1} has an order costing {2}.",
                                        order.Customer.Firstname, order.Customer.Lastname,
                                        order.Total));
    }
    Console.WriteLine();

    // Update the first order.
    Order firstOrder = q.FirstOrDefault();
    if (firstOrder != null)
    {
        firstOrder.Total += 10;
        context.SaveChanges();
    }

    // Display the order once more.
    foreach (var order in q)
    {
        Console.WriteLine(String.Format("{0} {1} has an order costing {2}.",
                                        order.Customer.Firstname, order.Customer.Lastname,
                                        order.Total));
    }

    Console.ReadLine();
}

A new connection (context) is made to the database and the orders are queried and displayed. Next the first order found is updated and finally the orders are displayed once more.

All this happens using the same ObjectContext (see the using statement). It tracks the changes made to the order objects and generates the necessary SQL to persist these changes in the database upon the call to context.SaveChanges().

Figure 7 – The Output
Orders output

If you’re interested in finding out what the generated SQL looks like I recommend using the AnfiniL’s SQL Express Profiler tool. It’s free and easy to use.

Top of page

Shared ObjectContext

You can as the previous example has shown create an ObjectContext when needed and dispose of it immediately after. However you can also choose to share the same ObjectContext accross multiple methods, instances…etc. if you want to limit the amount of ObjectContext instances in your application.

One way of doing this is to encapsulate the ObjectContext in a class that adheres to the singleton pattern. Take a look at the code in Listing 2.

Listing 2 – Shared ObjectContext

public class SharedObjectContext
{
    private readonly WestwindEntities context;
    
    #region Singleton Pattern

    // Static members are lazily initialized.
    // .NET guarantees thread safety for static initialization.
    private static readonly SharedObjectContext instance = new SharedObjectContext();

    // Make the constructor private to hide it. 
    // This class adheres to the singleton pattern.
    private SharedObjectContext()
    {
        // Create the ObjectContext.
        context = new WestwindEntities();
    }

    // Return the single instance of the ClientSessionManager type.
    public static SharedObjectContext Instance
    {
        get
        {
            return instance;
        }
    }   

    #endregion

    public WestwindEntities Context
    {
        get
        {
            return context;
        }
    }
}

The following Listing shows how you would use this shared ObjectContext.

Listing 3 – Usage Of The Shared ObjectContext

WestwindEntities context = SharedObjectContext.Instance.Context;

var q = from o in context.Orders.Include("Customer") orderby o.Total select o;

foreach (var order in q)
{
    Console.WriteLine(String.Format("{0} {1} has an order costing {2}.",
                                    order.Customer.Firstname, order.Customer.Lastname,
                                    order.Total));
}

Console.ReadLine();

You can find this code in the ConsoleSharedObjectContext project included in the demo source code.

Remark: Limit the scope of the ObjectContext. It is recommended to use the ObjectContext instance within a using statement. This ensures that the resources associated with the ObjectContext are automatically disposed when the using statement exists. Make sure your application benefits from a shared ObjectContext, for instance if you bind control to objects maintained by the ObjectContext.

Top of page

ObjectContext in ASP.NET

To quote MSDN: “The ObjectContext class is not thread safe. The integrity of data objects in an ObjectContext cannot be ensured in multi-threaded scenarios.”.

This rules out using the afore mentioned approach in an ASP.NET environment as it is inheritly multi-threaded. Each request is handled by a separate thread. To circumvent the problem the solution is to use an ObjectContext per Http request. The following Listing shows one possible approach.

Listing 4 – ObjectContext Per Http Request

public static class ObjectContextPerHttpRequest
{
    public static WestwindEntities Context
    {
        get
        {
            string objectContextKey = HttpContext.Current.GetHashCode().ToString("x");
            if (!HttpContext.Current.Items.Contains(objectContextKey))
            {
                HttpContext.Current.Items.Add(objectContextKey, new WestwindEntities());
            }
            return HttpContext.Current.Items[objectContextKey] as WestwindEntities;
        }
    }
}

To demonstrate its usage add a new Web Application project to the solution, add the necessary references to the DAL project and the System.Data.Entity assembly. Finally add the connection string to the Web.config file.

Open up the default.aspx page in design view and add a GridView. Add the following code to the code-behind in the Page_Load(…) event handler to bind some data to the grid.

Listing 5 – Default.aspx.cs code-behind

protected void Page_Load(object sender, EventArgs e)
{
    WestwindEntities context = ObjectContextPerHttpRequest.Context;
    GridView1.DataSource = from c in context.Customers select c;
    GridView1.DataBind();
}

The output is a list of the customers.

Figure 8 – The Output In ASP.NET
ObjectContext in ASP.NET

Top of page

Summary

While there is much debate going on about the Entity Framework I certainly feel that this first release offers a valid alternative to any prior existing data access technologies.

Working with the Entity Framework entails dealing with the ObjectContext. As demonstrated the way the ObjectContext is too be handled depends on the target platform. Sharing the ObjectContext on one thread poses no problem (Windows Applications), however as soon as you end up in a multi-threaded environment (ASP.NET) you must implement some custom logic to ensure the integrity of the data objects within the ObjectContext.

Top of page

Download

You can find the source code for this article on the Download page of this blog.

Top of page

About these ads

12 Responses to “Entity Framework ObjectContext”

  1. wouter Says:

    When using a singleton you will be not be able to use :

    using( WestwindEntities context = ObjectContextPerHttpRequest.Context)
    {
    //code here.
    }

    You are able to use it but only once.

    How are you going to dispose your (singleton) object in ASP.NET applications?

  2. Christophe Says:

    You could opt to implement the Dispose pattern so that you can dispose of the ObjectContext when using the SharedObjectContext. Take a look at the following blog post on Haacked.com for more information on the Dispose pattern:

    http://haacked.com/archive/2005/11/18/ACloserLookAtDisposePattern.aspx

    Or you could opt not to use a singleton at all and create a new ObjectContext each time you request one using the SharedObjectContext class. You could then use this newly created ObjectContext for as long as your code requires.

    • Rakoun Says:

      I read the article about the Dispose pattern but I don’t understand what you mean.
      Did my singleton class SharedObjectContext must inherit from DisposeObject???
      My problem is with Transaction. I can call more then one BeginTransaction on my Connection object.

      Regards.

  3. Shimmy Says:

    I developed an asp.net project in this way, so the ObjectContext is initialized in each request.
    First I added some disposing functionality to the ObjectContext via its partial class, then I created a class BasePage.cs that inherits from System.Web.UI.Page and added the ObjectContext as a property, then all pages in the project inherit from this base page.

    //1)
    partial class Entities
    {
    public bool IsDisposed { get; private set; }

    protected override void Dispose(bool disposing)
    {
    base.Dispose(disposing);
    IsDisposed = true;
    }
    }

    //2)
    public class BasePage : Page
    {
    private Entities m_DataContext;
    public Entities DataContext
    {
    get
    {
    if (m_DataContext == null || m_DataContext.IsDisposed) m_DataContext = new Entities();
    return m_DataContext;
    }
    }

    public override void Dispose()
    {
    if (m_DataContext != null && !m_DataContext.IsDisposed) m_DataContext.Dispose();
    }
    }

    //3)
    partial class SearchPage : BasePage
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    Contact contact = DataContext.Contacts.FirstOrDefault();
    }
    }

    Is there a problem with it?


  4. Thanks a ton. I am developing mvccms and had this as the get in my global objectcontext provider

    //if (_mvccmsEntities == null)
    //{
    // _mvccmsEntities = new MvcCmsEntities();
    //}
    //return _mvccmsEntities;

    I changed it to

    string objectContextKey = HttpContext.Current.GetHashCode().ToString(“x”);
    if (!HttpContext.Current.Items.Contains(objectContextKey))
    {
    HttpContext.Current.Items.Add(objectContextKey, new MvcCmsEntities());
    }
    _mvccmsEntities = HttpContext.Current.Items[objectContextKey] as MvcCmsEntities;
    return _mvccmsEntities;

    And I am doing good. I really wasn’t looking forward to being forced to use a injection container and having to keep up with Unity or something like that. I knew there had to be a simple way to tie the context to the request. Thank you so much for the simple answer.

  5. Stu Says:

    Thanks for the tip on using an ObjectContext Per Http Request. That really helped me out.

  6. Wes Stueve Says:

    It seems like this would not be a reusable pattern for applications, although, I know the ObjectContext should be short lived. It also seems messy to couple the data access to the web. At any rate, I though once per thread might be the way to go. See any problems with this other than it might live too long for a long running thread?

    public class ThreadObjectContextProvider
    {
    [ThreadStatic]
    private static MyEntities _Context;
    public static MyEntities Context
    {
    get
    {
    if (_Context == null) _Context = new MyEntities();
    return _Context;
    }
    }
    }

    • Christophe Says:

      Hi,

      Don’t use a [ThreadStatic] attribute on a static member when you’re using it within an ASP.NET environment. ThreadStatic storage is tied to the thread, not the HttpContext.

      In ASP.NET your code is run on a thread from the ASP.NET thread pool. Your ThreadStatic variable will be reused by every other request that this thread has to handle.

      For more information please read:

      http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx

      Storing the ObjectContext on the HttpContext.Current.Items is a pretty common technique. This way it is unique to your request…and shortlived…as requests should be handled as quickly as possible.

      Regards,

      Christophe

      • Wes Stueve Says:

        That’s some good information to know. I didn’t think about a ThreadPool, but makes perfect sense. I tried to see if it calls Dispose on the objects when returned to the pool or anything that I can tell for reuse, and it doesn’t appear to. Thanks a lot for the reply and information.

  7. product Says:

    hey there and thank you for your information –
    I’ve certainly picked up anything new from right here. I did however expertise some technical points using this web site, as I experienced to reload the site many times previous to I could get it to load properly. I had been wondering if your web host is OK? Not that I’m complaining, but
    sluggish loading instances times will very frequently affect your placement in google and could damage your high-quality
    score if advertising and marketing with Adwords.
    Anyway I’m adding this RSS to my e-mail and could look out for a lot more of your respective interesting content. Ensure that you update this again very soon.


  8. […] Entity Framework ObjectContext | Christophe Geers’ Blog. […]


Comments are closed.

Follow

Get every new post delivered to your Inbox.

Join 342 other followers

%d bloggers like this: