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

How to use a dbcontext in a static class? (ObjectDisposedException)

嘿,我最近刚学会了如何使用扩展方法,很高兴能在我当前的项目中实现它。

我的objective: 我想在助手 class 中检查我的 table 中是否存在条目,因为我将在多个控制器中使用它来确定要显示的导航 link在我的导航栏中:

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

目前配置在Startup.csclass。

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

ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'ApplicationDbContext'.

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

我尝试阅读此 link 但它对我没有帮助,因为它需要 Startup.cs class.[=18= 中的 ApplicationBuilder ]

解决方案更新 我在每次方法调用后都处理了 dbcontext,因为我将它放入了一个变量中。相反,我直接在传递的上下文中调用它并且它有效:

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

其次,扩展不应该与数据库之类的东西交互。特别是此处,扩展的静态性质与 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());

永远不要将 DbContext 声明为静态的,这会导致各种麻烦,并且不会刷新数据,因此您将从查询中获取旧数据。一个选项是每次使用它时都在静态方法中实例化它,就像这样:

public static MyClass Example
{
        public static bool MyStaticMethod(long id)
        {
            MyDBContext db = new MyDBContext();
            //use db context now....
        }
}