0

I have refactored some querys on linq in order to have two calls:

public IQueryable<Entity> GetAll()
{
   return context.Set<ENTITY>().Project().To<Entity>();
}

That is called from:

public int FindLastID()
{
    using(var context = new DBContext())
    {
       return GetAll().Max(p => p.id);
    }
}

The problem is that GetAll should be independently used, and it has no context. If the using context in wirtten on the GetAll method it is disposed and the Max function generates an excetion.

Is any way of calling the GetAll with no exception?

Alberto
  • 15,626
  • 9
  • 43
  • 56
amalbala
  • 118
  • 1
  • 12
  • 1
    Pass `GetAll()` the context. `context` looks like a field on the class which contains `GetAll()`? – Sam Leach Feb 17 '14 at 13:17
  • But if GetAll is directly called from the service layer, It should create the context in this case. – amalbala Feb 17 '14 at 13:19
  • See http://stackoverflow.com/questions/3362280/entity-framework-4-objectcontext-lifetime – Sam Leach Feb 17 '14 at 13:22
  • You don't need to create a context in the FindLastID method. And why do you write context.Set().Project().To()? Replace it with context.Set().AsQueryable(); – ssimeonov Feb 17 '14 at 13:24
  • The projection is part of Automapper, I am converting the Entity Framework class into my domain class. if the context is created on the service layer this the Service class in coupled with a DB repository, I would like to decouple the service layer from the persistence layer. So the repository are injected into the service layer, and sometimes are DB and sometimes files, etc – amalbala Feb 17 '14 at 13:32

2 Answers2

1

Usually all repository methods assume that a context is created. This is the most convenient way. So your FindLastID method also shouldn't create the context, unless it's a service layer method. One simple example is to use a static variable:

public void AServiceMethod()
{
    using (var context = contextProvider.CreateContext())
    {
        // call some domain operations, which use repositories

        // commit 
    }
}

Where CreateContext will open a DB session and store it in some static variable accessible from all repositories. This is not very elegant, but often is sufficient. To make it better you can use IoC as suggested by Sergey Berezovskiy. Also you may be interested in this article, recommended by Sam Leach in his answer.

Alternatively you could try something like this:

public IQueryable<Entity> GetAll()
{
    return GetAll(null);
}

public IQueryable<Entity> GetAll(DBContext context)
{
    if (context == null)
    {
        using (context = new DBContext())
        {
            return GetAll(context);
        }
    }

    return context.Set<ENTITY>().Project().To<Entity>();
}

But I'd recommend the first approach, as it's simpler and easier to maintain, comprehend.

Community
  • 1
  • 1
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • 1
    +1 for first approach. Injecting context into repository is the best way – Sergey Berezovskiy Feb 17 '14 at 13:25
  • I don't know if I like this. You could have the context as a field and dispose it from outside. – Sam Leach Feb 17 '14 at 13:26
  • So the Service class is coupled to the DB repository? – amalbala Feb 17 '14 at 13:34
  • Thanks! It is clear that I will use Ninject to inject the context into the service method using something similar to http://stackoverflow.com/questions/11921883/how-to-handle-dbcontext-when-using-ninject I just need to figure out how to solve when the queries are not related to the DB and the repositories are associated to text files. – amalbala Feb 17 '14 at 13:51
0

This question is about Entity Framework Context Management.

See this MSDN article, Working with DbContext

It gives some general guidelines that you might find useful while thinking about refactoring and designing your data access.

When working with long-running context consider the following:

As you load more objects and their references into memory, the memory consumption of the context may increase rapidly. This may cause performance issues.

Remember to dispose of the context when it is no longer required.

If an exception causes the context to be in an unrecoverable state, the whole application may terminate.

The chances of running into concurrency-related issues increase as the gap between the time when the data is queried and updated grows.

When working with Web applications, use a context instance per request.

When working with Windows Presentation Foundation (WPF) or Windows Forms, use a context instance per form. This lets you use change-tracking functionality that context provides.

Using an IoC framework to manage the lifetime of your context is probabably the best approach as Sergey Berezovskiy said.

Also, see this old (but good) article about context lifetime management.

Community
  • 1
  • 1
Sam Leach
  • 12,746
  • 9
  • 45
  • 73
  • Thanks, reviewing your link, it seems that storing the context on HttpContext.Current.Items is the sugested solution for having one context per request. – amalbala Feb 17 '14 at 13:43