在MVC控制器中处理EF DBContext

时间:2017-07-30 03:11:04

标签: c# asp.net-mvc entity-framework

我想确保我正在处理我的EF dbContext对象。

目前我正在使用静态方法来调用EF crud操作,以便将所有数据层内容保持黑盒子并且不在控制器之外。

下面的示例我有一个方法返回IQueryable并使用Using statment,当查询尝试在已处置的上下文对象上运行时会导致异常。

另一个不使用Using语句并且工作正常但它是否被处理?

我应该只返回IEnumerable而不是IQueryable吗?

public class MyContext : DbContext
{
    public MyContext() : base("MyConnectionString")
    {
        Database.SetInitializer<EFContext>(null);
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
}


public class Data
{
    // Fails when IQuerable tried to run against a disposed MyContext object
    public static T Get<T>(params string[] joins)
    {
        using (var context = new MyContext())
        {
            return context.Get<T>(joins);
        }
    }

    // Works fine but when is it disposed?
    public static T Get<T>(params string[] joins)
    {
        return new MyContext().Get<T>(joins);
    }
}

public ActionResult GetUser(int id = 0)
{
    var data = Data.Get<User>();
    return View("Users", model);
}

1 个答案:

答案 0 :(得分:4)

问题与使用IQueryableIEnumerable无关。您有异常,因为通过返回IQueryableIEnumerable,您没有执行LINQ。您刚刚打开了与数据库的连接,然后在配置查询后关闭。

要解决此问题,您需要通过调用ToListToArraySingle[OrDefault]First[OrDefault]等扩展方法来执行LINQ查询。

由于您正在使用Web应用程序,因此最佳做法是在Web请求的整个生命周期中拥有DbContext的一个实例。我建议你使用DI(依赖注入),它会帮助你很多。您可以尝试Simple Injector这是非常简单的DI。

如果您无法使用DI,请按照以下步骤操作,但请花点时间了解DI请::)

  1. 当网络请求到达时,请将DbContext的新实例存储到HttpContext.Items个收藏中。
  2. 在您的方法中,只需从DbContext检索存储的HttpContext.Items并使用它。
  3. 当网络请求终止时,只需处置DbContext