Asp.net 在上一个操作之前,在此上下文上启动了第二个操作
我在使用EntityFramework时有一个常见错误,但我无法找出原因。错误是 “在上一个操作之前,在此上下文上启动了第二个操作 操作已完成。这通常是由使用 DbContext的相同实例。有关如何避免 DbContext的线程问题,请参阅 " 我正在使用GraphQL中间件来处理请求 堆栈跟踪:Asp.net 在上一个操作之前,在此上下文上启动了第二个操作,asp.net,entity-framework,graphql,dbcontext,Asp.net,Entity Framework,Graphql,Dbcontext,我在使用EntityFramework时有一个常见错误,但我无法找出原因。错误是 “在上一个操作之前,在此上下文上启动了第二个操作 操作已完成。这通常是由使用 DbContext的相同实例。有关如何避免 DbContext的线程问题,请参阅 " 我正在使用GraphQL中间件来处理请求 堆栈跟踪: at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection() at Microsoft
at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Test.DataAccess.Intranet.Repository.Admin.UserModule.Query.GetUserDataQuery.Execute(String username) in C:\Projects\GIT Projects\SWDi\Intranet\Test.Backend\Test.DataAccess.Intranet\Repository\Modules\Admin\UserManagement\Query\Implementation\GetUserDataQuery.cs:line 34
at Test.Web.Base.Services.UserService.GetUserContext(HttpContext context) in C:\Projects\GIT Projects\Test\Intranet\Test.Backend\Test.Web.Base\Services\UserService.cs:line 55
at Test.API.Middleware.GraphQLMiddleware.InvokeAsync(HttpContext httpContext) in C:\Projects\GIT Projects\Test\Intranet\Test.Backend\Test.Web.API\Middleware\GraphQLMiddleware.cs:line 71
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Test.Web.API.Middleware.NtlmAndAnonymousSetupMiddleware.Invoke(HttpContext context) in C:\Projects\GIT Projects\Test\Intranet\SWDi.Backend\Test.Web.API\Middleware\NtlmAndAnonymousSetupMiddleware.cs:line 39
at Test.API.Middleware.ExceptionMiddleware.Invoke(HttpContext context) in C:\Projects\GIT Projects\Test\Intranet\Test.Backend\Test.Web.API\Middleware\ExceptionMiddleware.cs:line 40"
在这里,我在graphqlmidware.cs中处理POST请求:
public async Task InvokeAsync(HttpContext httpContext)
{
if (
(httpContext.Request.Path.StartsWithSegments(CATCHURLPATH) || httpContext.Request.PathBase.StartsWithSegments(CATCHURLPATH))
&& string.Equals(httpContext.Request.Method, CATCHURLMETHOD, StringComparison.OrdinalIgnoreCase))
{
string body;
var userContext = await this.userService.GetUserContext(httpContext);
using (var streamReader = new StreamReader(httpContext.Request.Body))
{
body = await streamReader.ReadToEndAsync();
var request = JsonConvert.DeserializeObject<GraphQLQueryBase>(body);
var result = await this.executor.ExecuteAsync(doc =>
{
doc.ThrowOnUnhandledException = true;
doc.Schema = this.schema;
doc.Query = request.Query;
doc.Inputs = request.Variables.ToInputs();
doc.ExposeExceptions = true;
doc.UserContext = new Dictionary<string, object>()
{
{ "UserId", userContext.UserId },
{ "Username", userContext.Username },
};
}).ConfigureAwait(false);
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
Task.Factory.StartNew(() => this.queryLogMutation.Execute(userContext.UserId, request.Query));
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
httpContext.Response.ContentType = "application/json";
await this.writer.WriteAsync(httpContext.Response.Body, result);
}
}
else
{
await this.next(httpContext);
}
}
最后是getUserByUsername
查询:
public class GetUserDataQuery : IGetUserDataQuery
{
/// <summary>
/// Initializes a new instance of the <see cref="GetUserDataQuery"/> class.
/// </summary>
/// <param name="context">Intranet Context by DI.</param>
public GetUserDataQuery(IntranetContext context)
{
this.Context = context;
}
private IntranetContext Context { get; }
/// <summary>
/// Get the Intranet user context using the users (AD) username.
/// </summary>
/// <param name="username">The username.</param>
/// <returns>The DB user context.</returns>
public async Task<MainUserModel> Execute(string username)
{
var userInformation = await this.Context.VUser.Where(x => x.Username == username).SingleOrDefaultAsync();
var userRights = await this.Context.UserModule.Where(x => x.UserId == userInformation.UserId).Include(x => x.RefModule).ToListAsync();
var userFunctions = await this.Context.UserModuleFunction.Where(x => x.UserId == userInformation.UserId).Include(x => x.RefModuleFunction).ToListAsync();
var memberList = await this.Context.UserGroupMember.Where(x => x.UserId == userInformation.UserId).Include(x => x.UserGroup).ToListAsync();
var isCashier = await this.Context.UserCashbox.Where(x => x.UserId == userInformation.UserId).AnyAsync();
return new MainUserModel(userInformation, userFunctions, userRights, memberList, isCashier);
}
}
公共类GetUserDataQuery:IGetUserDataQuery
{
///
///初始化类的新实例。
///
///由DI提供的Intranet上下文。
公共GetUserDataQuery(IntranetContext上下文)
{
this.Context=Context;
}
私有IntranetContext上下文{get;}
///
///使用用户(AD)用户名获取Intranet用户上下文。
///
///用户名。
///数据库用户上下文。
公共异步任务执行(字符串用户名)
{
var userInformation=wait this.Context.VUser.Where(x=>x.Username==Username.SingleOrDefaultAsync();
var userRights=wait this.Context.UserModule.Where(x=>x.UserId==userInformation.UserId);
var userFunctions=wait this.Context.UserModuleFunction.Where(x=>x.UserId==userInformation.UserId).Include(x=>x.RefModuleFunction.toListSync();
var memberList=wait this.Context.UserGroupMember.Where(x=>x.UserId==userInformation.UserId).Include(x=>x.UserGroup.toListSync();
var isCashier=wait this.Context.UserCashbox.Where(x=>x.UserId==userInformation.UserId).AnyAsync();
返回新的MainUserModel(用户信息、用户函数、用户权限、成员列表、iCashier);
}
}
即使我将我的dbContext
设置为瞬态,检查是否有忘记的async/await关键字,甚至是嵌套的async,错误仍然会发生。
如果您需要进一步的信息或有任何想法,请让我知道。在线`var dbuser=等待此消息。GetUserByUserName查询…`
getUserByUsernameQuery
是如何构造和分配的?@DavidBrowne-Microsoft我添加了剩余的userService代码。userService
从哪里获取其IGetUserDataQuery
构造函数参数?@DavidBrowne-Microsoft我不太确定您需要看到什么。我对.NET相当缺乏经验。你能详细说明一下吗?对于初学者来说,这是一个相当复杂的设计。该错误告诉您,您的IntranetContext
被两个不同的操作同时使用。您将IntranetContext
嵌入到多个级别的服务中,因此您必须跟踪如何实例化这些服务并管理它们的生命周期。如果其中一个是单例,或者如果您显式地并行使用它们,则可能会导致此错误。
public class GetUserDataQuery : IGetUserDataQuery
{
/// <summary>
/// Initializes a new instance of the <see cref="GetUserDataQuery"/> class.
/// </summary>
/// <param name="context">Intranet Context by DI.</param>
public GetUserDataQuery(IntranetContext context)
{
this.Context = context;
}
private IntranetContext Context { get; }
/// <summary>
/// Get the Intranet user context using the users (AD) username.
/// </summary>
/// <param name="username">The username.</param>
/// <returns>The DB user context.</returns>
public async Task<MainUserModel> Execute(string username)
{
var userInformation = await this.Context.VUser.Where(x => x.Username == username).SingleOrDefaultAsync();
var userRights = await this.Context.UserModule.Where(x => x.UserId == userInformation.UserId).Include(x => x.RefModule).ToListAsync();
var userFunctions = await this.Context.UserModuleFunction.Where(x => x.UserId == userInformation.UserId).Include(x => x.RefModuleFunction).ToListAsync();
var memberList = await this.Context.UserGroupMember.Where(x => x.UserId == userInformation.UserId).Include(x => x.UserGroup).ToListAsync();
var isCashier = await this.Context.UserCashbox.Where(x => x.UserId == userInformation.UserId).AnyAsync();
return new MainUserModel(userInformation, userFunctions, userRights, memberList, isCashier);
}
}