在创建模型时无法使用上下文的异常,与ASP.NET Identity相关。

48

为什么我们调用AccountApiController.Register()方法时会出现这种情况?

  • 谁试图使用上下文?
  • 谁试图创建上下文?
  • 我们如何避免这种情况?
  • 我们如何调试这个问题?

"Message":"发生错误",

"ExceptionMessage":"当前正在创建模型,无法使用上下文。如果在OnModelCreating方法内使用上下文或者多个线程同时访问同一上下文实例,则可能引发此异常。请注意,DbContext和相关类的实例成员不保证是线程安全的。",

"ExceptionType":"System.InvalidOperationException",

"StackTrace":"

at System.Web.Http.ApiController.d__1.MoveNext()

--- End of stack trace from previous location where exception was thrown

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

at System.Runtime.CompilerServices.TaskAwaiter .HandleNonSuccessAndDebuggerNotification(Task > task)

at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__0.MoveNext()"


2
请确保您不要在不同的请求中使用相同的上下文对象,并确保您在 OnModelCreating 之后发送请求。您可以在该方法结束处添加断点。 - Daniil Grankin
我们如何确保不为不同的请求使用相同的上下文对象?此外,我不确定您所说的添加断点是什么意思,因为我们没有 OnModelCreating 方法。 - Shaun Luttin
我了解到ASP.NET Identity使用工厂模式来获取每个请求的UserManager实例;这可能会成为一个问题,因为我们的UserManager将数据存储在我们的DbContext中。嗯。 - Shaun Luttin
尝试将您的方法设置为异步,这可能会解决问题。 - user2982369
7个回答

27

问题在于我们没有使用MS推荐的工厂模式。

您可以使用工厂实现从OWIN上下文中获取UserManager的实例。...这是获取每个请求的UserManager实例的推荐方式。

因此,“多个线程同时访问同一上下文实例”,因为多个请求和因此线程共享一个DbContext。

以下内容是正确的。它为每个对UserManagerFactory函数的调用创建一个新的MyDbContext实例。

UserManagerFactory 
= () => new UserManager<IdentityUser>(new UserStore<IdentityUser>(new MyDbContext()));

以下是错误的。它看起来相似,但没有为每个调用创建一个新的UserManagerFactory实例。这就是我们之前使用的,因此我们的网站出现了问题。

var userStore = new UserStore<IdentityUser>(new MyDbContext());                    
var userManager = new UserManager<IdentityUser>(userStore);
UserManagerFactory = () => userManager;

8
我应该把这个放在我的项目哪里?我使用Unity.Mvc作为依赖解析器。此外,我使用自己的UnityOfWork,在其中注入一个DbContext,该DbContext被所有仓库共用。 - Reuel Ribeiro
我也遇到了同样的错误信息,这个方法也解决了我的问题。@ShaunLuttin - Austin B
这里也遇到了同样的问题,通过添加工厂模式解决了。感谢 @ShaunLuttin。 - Mehdi

25

如果connectionString不正确,也会引发此错误。请检查connectionString是否有效(无拼写错误等)。


1

你是否重写了OnModelCreating方法?如果是,能否分享它或整个上下文类?

如果没有,请注意错误消息中的以下内容

或者多个线程同时访问同一上下文实例。请注意,DbContext和相关类的实例成员不能保证线程安全。

如果这不起作用,你是否使用Visual Studio创建的未更改的Web API项目?


我们不会覆盖OnModelCreating方法。此外,我们也不使用未更改的Web API项目...相反,我们修改了DbContext,该DbContext存储了ASP.NET Identity数据和其他网站数据。 - Shaun Luttin
1
我们不确定如何确定同一上下文实例是否被多个线程同时访问。嗯。 - Shaun Luttin

1
如果目标是模型种子数据,并且您正在使用实体框架,则强烈建议您查看以下链接:https://learn.microsoft.com/en-us/ef/core/modeling/data-seeding。此链接详细介绍了如何在迁移过程中直接添加种子数据。通常情况下,当您想要在创建数据库时添加种子数据而不是在应用程序启动时添加时,这将非常有用。

0

我正在使用EF Code First在多层架构中与MySQL一起使用,遇到了相同的异常,并且在DBContext类结构内使用以下行代码可以解决问题:

Database.SetInitializer<EntitiesName>(null);

0

我同意Shaun Luttin的主要答案,但也要补充说明:

在我的情况下:部署后,我遇到了这个错误,发现问题是在插入SSL证书后使用了Hsts Preload。取消注释这些行解决了重定向问题,并完全解决了此错误。

 //app.UseHsts(options => options.MaxAge(days: 18 * 7).IncludeSubdomains().Preload());

0

如果您正在从表/视图获取记录,请确保您对数据库对象具有足够的访问权限。

我曾经遇到过同样的问题,通过执行以下操作解决了它

sp_change_users_login [ @Action = ] 'action' [ , [ @UserNamePattern = ] 'user' ] [ , [ @LoginName = ] 'login' ] [ , [ @Password = ] 'password' ] [;]


sp_change_users_login 'update_one' 'dbuser' 'dblogin'

查找更多代码片段和详细信息


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