通过围绕数据库上下文的使用来确定LINQ语句的范围

时间:2018-12-05 22:58:50

标签: c# entity-framework linq entity-framework-6 c#-7.0

我有一个返回查询结果以进一步过滤的函数,如下所示:

public IQueryable<MyData> Query(string name) {
  using (var dbc = new MyDbContext()) 
    return dbc.MyData.Where(v => v.Name == name);
}

然后我在另一个函数中调用它:

public f() { 
  var res = Query("john").Select(v => ......
  var resList = res.ToList();
  ...
}

在这种情况下MyDbContext的范围是什么?什么时候处置? Query()返回时或ToList()中的f()完成时?

如果是前者,我该如何更改它,以便在ToList()完成时处置数据库上下文?

(注意:通常,我知道在EF中通常不需要使用DbContext,但是在这种情况下,我想解决sqlite锁定问题时就希望使用它)

谢谢!

1 个答案:

答案 0 :(得分:1)

好吧,using子句只是一个try finally块。因此Query将被转换为:

public IQueryable<MyData> Query(string name) {
  MyDbContext dbc;

  dbc = new MyDbContext();
  try
  {

     return dbc.MyData.Where(v => v.Name == name);
  }
  finally
  {
     dbc.Dispose();
  }   
}

Query返回IQueryable之后,很可能会立即处置上下文(甚至在调用.Select(v => ......之前)。

让调用者代替它来处理上下文有点“干净”。您可以在Query函数外部创建一个上下文对象,并将其作为参数传递:

public IQueryable<MyData> Query(MyDbContext dbc, string name) {
     return dbc.MyData.Where(v => v.Name == name);
}

public f() { 
  using(var dbc = new MyDbContext())
  {
      var res = Query(dbc, "john").Select(v => ......
      var resList = res.ToList();
      ...
  }      
}

总体思路很简单,建议不要过于复杂:

  1. 创建dbcontext
  2. 做任何您需要做的事
  3. 处理掉