如何在静态类中使用dbcontext? (的ObjectDisposedException)

时间:2017-09-26 16:59:54

标签: c# entity-framework extension-methods dbcontext asp.net-core-2.0

嘿,我刚刚学会了如何使用扩展方法,并非常兴奋地在我当前的项目中实现它。

我的目标: 我想检查我的表中是否存在辅助类中的条目,因为我将在多个控制器中使用它以确定要在导航栏中显示的导航链接:enter image description here

我的问题: 我不知道如何在我的静态助手类中访问我的dbcontext。我的dbcontext控制器接受一个参数,我不知道如何传递我的静态类。我认为创建一个新的dbcontext将解决我在下面解释的范围问题,但我不知道如何将option参数传递给我的构造函数。

enter image description here

它目前在Startup.cs类中配置。 enter image description here

我尝试了什么: 将ApplicationDbContext作为参数传递。这适用于我的控制器中的单个方法调用,但是当调用多个扩展方法时(要检查用户具有哪些游戏帐户),我得到一个ObjectDisposedException。

  

ObjectDisposedException:无法访问已处置的对象。此错误的常见原因是处理从依赖项注入解析的上下文,然后尝试在应用程序的其他位置使用相同的上下文实例。如果您在上下文中调用Dispose()或将上下文包装在using语句中,则可能会发生这种情况。如果使用依赖项注入,则应该让依赖项注入容器负责处理上下文实例。   对象名:'ApplicationDbContext'。

根据我的理解,这是一个范围问题,第一个方法调用在完成后处理上下文并且我试图在下一次调用中使用相同的上下文?我该怎么做才能解决这个问题?

我尝试阅读此链接Cannot access a disposed object in ASP.NET Core when injecting DbContext但它没有帮助我,因为它需要Startup.cs类中的ApplicationBuilder。

enter image description here

解决方案更新 我在每个方法调用之后都放置了dbcontext,因为我将它放入一个变量中。相反,我直接在传递的上下文上调用它并且它可以工作:

enter image description here

2 个答案:

答案 0 :(得分:5)

是的,所以,虽然这些扩展对您而言是新的和闪亮的,但这并不意味着您应该将它们用于所有事情。首先,扩展应该与它们正在操作的类型建立逻辑连接。例如,如果你有一个string,像ToUpper()这样的东西作为扩展名是有意义的,因为它修改并返回一个字符串。你正在尝试做的事情:只使用引用的值来返回完全外来的类型是违反扩展模式的。

其次,扩展不应与数据库之类的东西进行交互。特别是在这里,扩展的静态性质与EF上下文对象的概念完全不兼容。你甚至可以让它工作的唯一方法是每次在扩展中调用扩展时实际上新建一个上下文。这既是搞砸EF对象跟踪内容的好方法,也是泄漏内存的好方法。

多长时间,不要这样做。

如果您只是想要分解这些代码,那么您有更好的选择。例如,您实际上可以直接将方法添加到您的上下文中。

public class ApplicationDbContext : DbContext
{
    ...

    public bool HasDota2Account(string id)
    {
        return Dota2Accounts.Any(m => m.ApplicationUserId == id);
    }
}

然后,在您的控制器中,您可以执行以下操作:

var hasDota2Account = context.HasDota2Account(User.Identity.GetUserId());

答案 1 :(得分:0)

我遇到了类似的问题,决定使用dbContext作为私有静态只读成员,在静态stor(线程安全)中实例化

public static class PagingHelpers
    {
        private static readonly string _connectionString = ServiceLocator.Current.GetInstance<IConfiguration>().GetConnectionString("DefaultConnection"); // or conn.string
        private static readonly AppDbContext _dbContext=  new AppDbContext(new DbContextOptionsBuilder<AppDbContext>().UseSqlServer(_connectionString).Options);
        private static readonly IDictionary<int, string> departments = _dbContext.Departments.ToDictionary(p => p.DepartmentId, p => p.Name);