无法访问已释放的上下文实例 EF Core。

5
我正在使用 .net core mvc 和 EF 开发一个CRM系统,该系统需要大量的数据库连接以检索和更新信息。在调试过程中,我时常会遇到以下错误,这是一个拥有许多用户的大型项目,我不知道它在实际使用中会如何运作!
“无法访问已释放的上下文实例。此错误的常见原因是释放了从依赖项注入解析的上下文实例,然后在应用程序的其他地方尝试使用同一上下文实例。如果您正在调用上下文实例上的 'Dispose' 方法或将其包装在 using 语句中,则可能会出现此错误。如果您正在使用依赖项注入,则应让依赖项注入容器处理上下文实例的释放。\r\n对象名称:'XXX'。”
在之前,我在startup.cs中使用了以下设置:
services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY"))
                .ServiceLifetime.Singleton);

那个设置有时会导致另一个错误:

System.InvalidOperationException: 实体类型 'TblZZZ' 的实例无法被跟踪,因为已经有一个具有相同 {'ZZZId'} 键值的实例正在被跟踪。在附加现有实体时,请确保只附加一个具有给定键值的实体实例。

所以我将我的设置更改为:

services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY"))
                .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));

现在我遇到了 无法访问已释放的上下文实例 的问题。我不知道有什么设置可以解决我的问题。

我正在使用 net5.0

更新: 我的部分类:

public partial class TblXXX
    {
        private ZZZ context;//context
        public TblXXX(ZZZ _context)
        {
            context = _context;
        }
        public TblXXX() { }
//function for check username
   public bool CheckUsernameExit(string username) {
            var u = context.TblXXX
                .Where(e => e.Username == username)
                .FirstOrDefault();
            return (u != null);
        }
}

在我的控制器中:
  public IActionResult Check(UserModelView user)
        {
            if (ModelState.IsValid)
            {
                var r = _viewModel.tblXXX.CheckUsernameExit(user.tblXXX.Username);
                if (r)
                {
                    toastNotification.AddErrorToastMessage("This email is in use. Enter differernt email.");
                 
                    return View("Create", _viewModel);
                }
            

这是我的 ViewModel:

 public class UserModelView
    {
        public TblXXX tblXXX { get; set; }
        public List<TblXXX > tblXXXList { get; set; }
    }
          

这是我遇到错误的其中一种情况。


2
使用 AddDbContext<XXX> 并仅配置连接字符串即可,不要尝试修改服务生命周期,默认为 Scoped(应始终如此)。你一定在别的地方出了问题,我对此非常确定。现在你甚至不知道可能出了什么问题,我们可能都陷入困境了。 - King King
1
不要使用 Singleton 生命周期,根据在代码中的使用情况,使用 Scoped 或者甚至是 Transient。 - Crowcoder
可能是重复问题:https://stackoverflow.com/q/66531676/264697 - Steven
@KingKing,我已经更新了我的问题并附上了一个例子。如果您有时间,请看一下。 - Paria Shiri
1
谢谢您的回复,@KingKing。 - Paria Shiri
显示剩余5条评论
2个回答

15

我之前遇到了这个错误,因为我在控制器方法内部的一个方法上没有使用await。这导致函数在调用完成之前就返回并处理上下文。

图片描述在此


我曾经遇到过类似的情况,当时在数据库保存时进行了一个等待调用。然后,在成功保存之后,代码又进行了一次保存。就像你的例子展示的那样,我忘记了等待第二个数据库调用。谢谢! - LargeDachshund

6
在 asp.net core 中,DbContext 应该是 Scoped 服务,而不是 Singleton。
修改为:

将以下内容更改:

services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY"))
                .ServiceLifetime.Singleton);

To

services.AddDbContext<XXX>
                (option => 
                option.UseSqlServer(Configuration.GetConnectionString("YYY")));

不需要 ServiceLifetime.Scoped 吗?我应该移除 UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) 吗? - Paria Shiri
AddDbContext 将其创建为 Scoped 服务。其他选项由您决定。 - David Browne - Microsoft
通过对代码进行一些更改并使用@kingking的建议,现在我没有错误了。 - Paria Shiri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接