views:

308

answers:

4

I'm learning EF now and have a question regarding the ObjectContext:

Should I create instance of ObjectContext for every query (function) when I access the database?

Or it's better to create it once (singleton) and reuse it?

Before EF I was using enterprise library data access block and created instance of dataacess for DataAccess function...

+3  A: 

Definitely for every query. It's a lightweight object so there's not much cost incurred creating one each time you need it.

Besides, the longer you keep an ObjectContext alive, the more cached objects it will contain as you run queries against it. This may cause memory problems. Therefore, having the ObjectContext as a singleton is a particularly bad idea. As your application is being used you load more and more entities in the singleton ObjectContext until finally you have the entire database in memory (unless you detach entities when you no longer need them).

And then there's a maintainability issue. One day you try to track down a bug but can't figure out where the data was loaded that caused it.

Ronald Wildenberg
A: 

Don't use a singleton.. everyone using your app will share that and all sorts of crazy things will happen when that object context is tracking entities.

I would add it as a private member

Raj Kaimal
I mean singleton per session (every user gets it's own), and i plan to disable the tracking
verror
I agree with rwwilden's first response.
Raj Kaimal
+2  A: 

I think the most common way is to use it per request. Create it at the beginning, do what you need (most of the time these are operation that require common ObjectContext), dispose at the end. Most of DI frameworks support this scenario, but you can also use HttpModule to create context and place it in HttpContext.Current.Items. That is simple example:

public class MyEntitiesHttpModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += ApplicationBeginRequest;
        application.EndRequest += ApplicationEndRequest;
    }

    private void ApplicationEndRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Items[@"MyEntities"] != null)
            ((MyEntities)HttpContext.Current.Items[@"MyEntities"]).Dispose();
    }

    private static void ApplicationBeginRequest(Object source, EventArgs e)
    {
        var context = new MyEntities();
        HttpContext.Current.Items[@"MyEntities"] = context;
    }
}
LukLed
I think this is a less maintainable solution than simply creating an ObjectContext when you need one in the data layer. My objection against this solution is that you create a dependency between your UI layer and your data layer that isn't necessary. How you communicate with a database is an internal concern for the data layer. Second, it may seem easy at first to never have to worry about lazy-loading issues but some day you're trying to track down a bug and can't determine where it went wrong because you have no idea where the data that caused the bug was loaded (speaking from experience..)
Ronald Wildenberg
@rwwilden: Sorry, but how does it create dependency between UI and data layer? I am using repository pattern and repositories have to share context. Context is injected by DI container. Request is not that long and doesn't have so much operations that can cause so much problems. If you use proper patterns, you'll have no problems.
LukLed
@rwwilden: There were million questions about ObjectContext reusage, here on SO and other pages. Per request usage seems to dominate, it is not only my opinion.
LukLed
@LukLed About the dependency. Somewhere in your UI layer you have to say: new MyEntities(). The fact that you use entity framework for accessing data is an implementation detail of the data layer in my opinion.
Ronald Wildenberg
@LukLed I did a quick search on ObjectContext reuse but don't see a lot of consensus on the subject.
Ronald Wildenberg
@rwwilden: HttpModule is the only place to call `new MyEntities()`. DI does the rest. There is no way I would have to create context in UI.
LukLed
@LukLed But isn't the HttpModule part of the UI layer then?
Ronald Wildenberg
@rwwilden: I would say it is part of controller layer, but it doesn't really matter. It is instantiated once, can be really easily replaced with other code and there is actually no dependency. Context is passed to repository layer not by calling `HttpContext.Current.Items[@"MyEntities"]`, but with dependency injection rule.
LukLed
@rwwilden: I think that we both agree that storing context too long can be dangerous. Using per session or singleton can cause really serious problems. If you use it per operation and it works fine, ok. You can just have problems with objects in different contexts, that is also why I find using one context in request suitable. But still, the most important thing is not to keep it too long.
LukLed
@LukLed Agreed, keeping an ObjectContext alive too long is a bad idea.
Ronald Wildenberg
A: 

Like Luke says this question has been asked numerous times on SO.

For a web application, per request cycle seems to work best. Singleton is definitely a bad idea.

Per request works well because one web page has a User, maybe some Projects belonging to that user, maybe some Messages for that user. You want the same ObjectContext so you can go User.Messages to get them, maybe mark some messages as read, maybe add a Project and then either commit or abandon the whole object graph at the completion of the page cycle.

Hightechrider