嵌套调用linq操作的上下文重复

时间:2014-02-17 13:15:22

标签: c# linq entity-framework dbcontext

我已经在linq上重构了一些查询,以便进行两次调用:

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

来自:

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

问题是GetAll应该独立使用,而且没有上下文。如果在GetAll方法中使用了wirtten中的上下文,则它将被释放,并且Max函数会生成一个例外。

是否可以无异常地调用GetAll?

2 个答案:

答案 0 :(得分:1)

通常所有存储库方法都假定创建了一个上下文。这是最方便的方式。因此,除非是服务层方法,否则您的FindLastID方法也不应创建上下文。一个简单的例子是使用静态变量:

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

        // commit 
    }
}

其中CreateContext将打开数据库会话并将其存储在可从所有存储库访问的某个静态变量中。这不是很优雅,但往往就足够了。为了使其更好,您可以按照Sergey Berezovskiy的建议使用IoC。您也可能对this article Sam Leach推荐的his answer感兴趣。

或者你可以尝试这样的事情:

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>();
}

但我建议采用第一种方法,因为它更简单,更容易维护,理解。

答案 1 :(得分:0)

此问题与实体框架上下文管理

有关

请参阅此MSDN文章Working with DbContext

它提供了一些在考虑重构和设计数据访问时可能会发现有用的一般指导原则。

  

使用长时间运行的上下文时,请考虑以下事项:

     

和你一样   将更多对象及其引用加载到内存,即内存中   消费的背景可能会迅速增加。这可能会导致   性能问题。

     

请记住在没有的情况下处理上下文   需要更长时间

     

如果异常导致上下文出现在   不可恢复的状态,整个申请可能会终止。

     

机会   与并发相关的问题增加了之间的差距   查询和更新数据的时间会增加。

     

使用Web应用程序时,请按请求使用上下文实例。

     

使用Windows Presentation Foundation(WPF)或Windows窗体时,请使用   每个表单的上下文实例。这使您可以使用更改跟踪   上下文提供的功能。

使用IoC框架来管理上下文的生命周期可能是谢尔盖别列佐夫斯基所说的最佳方法。

另请参阅有关上下文生命周期管理的this old (but good)文章。