实体框架核心:在上一个操作完成之前,在此上下文上启动了第二个操作


88

我正在使用Entity Framework Core进行ASP.Net Core 2.0项目

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0"/>

在我的一种列表方法中,我收到此错误:

InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()

这是我的方法:

    [HttpGet("{currentPage}/{pageSize}/")]
    [HttpGet("{currentPage}/{pageSize}/{search}")]
    public ListResponseVM<ClientVM> GetClients([FromRoute] int currentPage, int pageSize, string search)
    {
        var resp = new ListResponseVM<ClientVM>();
        var items = _context.Clients
            .Include(i => i.Contacts)
            .Include(i => i.Addresses)
            .Include("ClientObjectives.Objective")
            .Include(i => i.Urls)
            .Include(i => i.Users)
            .Where(p => string.IsNullOrEmpty(search) || p.CompanyName.Contains(search))
            .OrderBy(p => p.CompanyName)
            .ToPagedList(pageSize, currentPage);

        resp.NumberOfPages = items.TotalPage;

        foreach (var item in items)
        {
            var client = _mapper.Map<ClientVM>(item);

            client.Addresses = new List<AddressVM>();
            foreach (var addr in item.Addresses)
            {
                var address = _mapper.Map<AddressVM>(addr);
                address.CountryCode = addr.CountryId;
                client.Addresses.Add(address);
            }

            client.Contacts = item.Contacts.Select(p => _mapper.Map<ContactVM>(p)).ToList();
            client.Urls = item.Urls.Select(p => _mapper.Map<ClientUrlVM>(p)).ToList();
            client.Objectives = item.Objectives.Select(p => _mapper.Map<ObjectiveVM>(p)).ToList();
            resp.Items.Add(client);
        }

        return resp;
    }

我有点迷茫,尤其是因为它在本地运行时可以运行,但是当我部署到我的登台服务器(IIS 8.5)时,我得到了这个错误,并且运行正常。当我增加一个模型的最大长度后,该错误开始出现。我还更新了相应视图模型的最大长度。而且还有许多其他列表方法非常相似,并且它们都在起作用。

我正在运行一个Hangfire作业,但是此作业没有使用相同的实体。我认为这就是很重要的。关于什么可能导致此的任何想法?


1
检查一下
Berkay

2
@Berkay我看到了这个问题以及许多其他类似的问题,并进行了尝试。我的方法是异步的,我使其同步以避免这些问题。我也尝试删除映射,也尝试删除.ToPagedList它继续引发错误。
安德烈·路易丝

很高兴看到完整的堆栈跟踪记录
Evk

并且要知道是否启用了多个活动结果
Jay

遇到同样的问题,我发现我的数据库表中有可为空的整数。一旦我将实体模型属性设置为与可为null的int匹配,它们就开始起作用,消息对我来说是一种误导...
AlwaysLearn '19

Answers:


87

我不确定您是否正在使用IoC和依赖注入在任何可能使用DbContext的地方进行解析。如果这样做,并且您正在使用.NET Core(或任何其他IoC-Container)中的本机IoC,但遇到此错误,请确保将DbContext注册为瞬态。做

services.AddTransient<MyContext>();

要么

services.AddDbContext<MyContext>(ServiceLifetime.Transient);

代替

services.AddDbContext<MyContext>();

AddDbContext将范围添加为上下文,这可能在使用多个线程时引起麻烦。

此外异步/ AWAIT操作可以通过异步lambda表达式时,会导致此行为。

将其添加为瞬态也有其缺点。您将无法在使用上下文的多个类上对某些实体进行更改,因为每个类都将获得自己的DbContext实例。

对此的简单解释是,该DbContext实现不是线程安全的。您可以在此处了解更多信息


1
当我使用瞬态时,出现以下连接错误(关闭或释放)“ OmniService.DataAccess.Models.OmniServiceDbContext”。System.ObjectDisposedException:无法访问已处置的对象。导致此错误的常见原因是,处理从依赖项注入中解决的上下文,然后稍后尝试在应用程序中的其他位置使用相同的上下文实例。如果在上下文上调用Dispose()或将上下文包装在using语句中,则可能会发生这种情况。...对象名称:“ AsyncDisposer”。
大卫,

3
嗨,大卫!我猜您正在使用Task.Run(async () => context.Set...)而不等待它,或者在不等待结果的情况下创建了作用域的db上下文。这意味着您的上下文在访问时可能已经被释放。如果您使用的是Microsoft DI,则必须在中自行创建一个依赖项范围Task.Run。还要查看这些链接。 stackoverflow.com/questions/45047877/…docs.microsoft.com/en-us/dotnet/api/…– alsami
42

3
如前所述,如果您错过使用await关键字调用异步方法,则会遇到此问题。
Yennefer '18

这对我有帮助。当我们从队列中收到新消息时,我正在从托管服务注入对新线程的依赖关系。使我的上下文暂时固定为例外
Cale

3
@alsami,你是我的英雄。6小时的痛苦调试。这就是解决方案。如果有人将IHttpContextAccessor注入DbContext中,并且Claims为null,则这是解决方案。非常感谢你。
jcmontx

55

在某些情况下,调用不带关键字的异步方法时会发生此错误await,只需await在方法调用之前添加即可解决。但是,答案可能与所提到的问题无关,但可以帮助解决类似的错误。


4
这发生在我身上。更改First()await / FirstAsync()工作。
Guilherme

赞成。另请参见jimlynn.wordpress.com/2017/11/16/…Jim Lynn“实体框架错误:在完成之前的操作之前,已在此上下文中开始第二次操作。任何实例成员均不保证得到安全保护。”
granadaCoder

谢谢你!这正是我的问题...忘记了在异步mdethod上添加一个等待。
AxleWack

发生在我身上的这句话也对我有所帮助,因为我搜索了我遗失的等待者。一旦找到,问题就解决了。
锡安·

42

异常意味着_context两个线程同时使用该线程。一个请求中的两个线程,或者两个请求中的两个线程。

_context声明的可能是静态的吗?不应该这样。

还是GetClients在同一请求中从代码的其他位置多次调用?

您可能已经在执行此操作,但理想情况下,您将对您使用依赖注入DbContext,这意味着您将AddDbContext()在Startup.cs中使用它,并且控制器构造函数将如下所示:

private readonly MyDbContext _context; //not static

public MyController(MyDbContext context) {
    _context = context;
}

如果您的代码不是这样,请向我们展示,也许我们可以提供进一步的帮助。


1
可能是我的工作。我设法解决了,请看我的答案。但我标记你的一样是正确的
安德烈·路易斯

我的代码就是这样,我们经常跟踪“在先前的异步操作完成之前,在此上下文中启动了第二个操作。使用'await'确保任何异步操作已完成,然后在此上下文上调用另一个方法。任何实例成员都不会保证是线程安全的。-位于System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered()“。
NMathur

@NMathur您是否_context在其他线程中使用对象?像里面一样Task.Run()吗?
加布里埃尔·卢西

@GabrielLuci我所有的方法都是异步的,如下所示,这会引起问题。我对这个话题的了解很少。您能建议我在哪里阅读哪些内容以了解这些行为?公共异步任务<List <Item >> GetItems(int orderId){List <Item> items =等待_context.Item.Where(x => x.OrderId == orderId)。退换货品; }
NMathur

@NMathur看起来不错。只要确保您始终使用await异步方法即可。如果您不使用await,则可能会无意间进入多线程。
加布里埃尔·卢西

8
  • 使用Startup.cs文件中的这一行代码解决我的问题。
    添加临时服务意味着每次请求服务时,在使用依赖注入时都会创建一个新实例。

           services.AddDbContext<Context>(options =>
                            options.UseSqlServer(_configuration.GetConnectionString("ContextConn")),
                 ServiceLifetime.Transient);
    

6

我遇到了同样的问题,事实证明父母服务是一个辛格尔顿。因此,上下文也自动变成了辛格尔顿。即使在DI中被声明为“ Per Life Life Scoped”。

将不同生命周期的服务注入另一个

  1. 切勿将范围和临时服务注入Singleton服务。(这有效地将瞬态或作用域服务转换为单例。)

  2. 切勿将瞬态服务注入范围服务(这会将瞬态服务转换为范围服务。)


这正是我的问题
Jonesopolis

这也是我的问题。我将处理程序类注册为单例,将DbContext注册为瞬态。每当处理程序被
命中时,

5

我有同样的错误。之所以发生是因为我调用了一种构造为public async void ...而不是的方法public async Task ...


4

我认为这个答案仍然可以帮助一些人并节省很多时间。我通过更改IQueryableList(或更改为数组,集合...)解决了类似的问题。

例如:

var list=_context.table1.where(...);

var list=_context.table1.where(...).ToList(); //or ToArray()...

2
恕我直言,这个答案不值得负分,只是表达不佳。.ToList()确实解决了大多数问题“第二次操作...”,因为它迫使表达式立即求值。这样,就没有排队上下文操作。
vassilag

这就是我的问题。我在查询的where子句中有xxx.Contains(z.prop)。xxx被认为是从早期查询中解析出来的独特的int []数组。不幸的是,当第二个查询命中时,xxx仍然是一个IQueryable。在第二个查询之前添加xxx.ToArray()解决了我的问题。
杰森·布泰拉

2

我遇到了同样的问题,但原因并非以上所列。我创建了一个任务,在任务内部创建了一个作用域,并要求容器获得服务。效果很好,但是随后我在任务中使用了第二项服务,但我忘记了也要求将其用于新范围。因此,第二个服务使用的是已处置的DbContext。

Task task = Task.Run(() =>
    {
        using (var scope = serviceScopeFactory.CreateScope())
        {
            var otherOfferService = scope.ServiceProvider.GetService<IOfferService>();
            // everything was ok here. then I did: 
            productService.DoSomething(); // (from the main scope) and this failed because the db context associated to that service was already disposed.
            ...
        }
    }

我应该这样做:

var otherProductService = scope.ServiceProvider.GetService<IProductService>();
otherProductService.DoSomething();

仅在using块中的所有内容完成执行后,才会公开上下文吗?
Sello Mkantjwa

处置该行为时,所有内容均置于该范围内。如果您有一个在后台运行的任务,并且该任务的时间比该操作要长,那么除非您为该任务创建一个新的作用域(如我在示例中所做的那样),否则就会遇到此问题。另一方面,如果您的任务可能要花费很长时间,或者您想100%确保它可以运行,则可能需要使用队列。如果使用的是Azure,则可以使用服务总线队列。
弗朗西斯科·金斯坦

2

实体框架核心不支持在同一DbContext实例上运行的多个并行操作。这包括async查询的并行执行以及来自多个线程的任何显式并发使用。因此,始终await async立即调用,或DbContext对并行执行的操作使用单独的实例。


1

我的情况有所不同:我试图为30个用户(属于特定角色)播种数据库,所以我运行以下代码:

for (var i = 1; i <= 30; i++)
{
    CreateUserWithRole("Analyst", $"analyst{i}", UserManager);
}

这是一个同步功能。在其中,我有3个呼叫:

UserManager.FindByNameAsync(username).Result
UserManager.CreateAsync(user, pass).Result
UserManager.AddToRoleAsync(user, roleName).Result

当我换成.Result.GetAwaiter().GetResult(),这个错误就走开了。


0

我收到同样的消息。但这对我来说没有任何意义。我的问题是我错误地使用了“ NotMapped”属性。在某些情况下,它可能仅意味着Linq语法或模型类错误。该错误消息似乎具有误导性。该消息的原始含义是,您不能在同一请求中多次在同一dbcontext上调用异步。

[NotMapped]
public int PostId { get; set; }
public virtual Post Post { get; set; }

您可以查看此链接以获取详细信息, https://www.softwareblogs.com/Posts/Details/5/error-a-second-operation-started-on-this-context-before-a-previous-operation-completed


0

我有一个后台服务,该服务为表中的每个条目执行操作。问题是,如果我在DbContext的同一实例上迭代并修改所有数据,则会发生此错误。

如该线程中所述,一种解决方案是通过将DbContext的生存期定义为

services.AddDbContext<DbContext>(ServiceLifetime.Transient);

但是由于我在多个不同的服务中进行了更改,并使用该SaveChanges()方法一次提交了该解决方案,因此在我的情况下不起作用。

因为我的代码在服务中运行,所以我在做类似的事情

using (var scope = Services.CreateScope())
{
   var entities = scope.ServiceProvider.GetRequiredService<IReadService>().GetEntities();
   var writeService = scope.ServiceProvider.GetRequiredService<IWriteService>();
   foreach (Entity entity in entities)
   {
       writeService.DoSomething(entity);
   } 
}

就能像简单的请求一样使用该服务。因此,要解决此问题,我只将单个作用域分为两个,一个用于查询,另一个用于写操作,如下所示:

using (var readScope = Services.CreateScope())
using (var writeScope = Services.CreateScope())
{
   var entities = readScope.ServiceProvider.GetRequiredService<IReadService>().GetEntities();
   var writeService = writeScope.ServiceProvider.GetRequiredService<IWriteService>();
   foreach (Entity entity in entities)
   {
       writeService.DoSomething(entity);
   } 
}

这样,实际上就有两个不同的DbContext实例被使用。

另一个可能的解决方案是确保在开始迭代之前读取操作已终止。在我的情况下,这不是很实际,因为可能需要将很多结果全部都加载到内存中才能执行该操作,而我首先尝试使用Queryable来避免这种结果。


0

我设法通过传递IQueryable一个方法来解决该错误,然后将该IQueryable“列表”用作对同一上下文的另一个查询的一部分。

public void FirstMethod()
{
    // This is returning an IQueryable
    var stockItems = _dbContext.StockItems
        .Where(st => st.IsSomething);

    SecondMethod(stockItems);
}

public void SecondMethod(IEnumerable<Stock> stockItems)
{
    var grnTrans = _dbContext.InvoiceLines
        .Where(il => stockItems.Contains(il.StockItem))
        .ToList();
}

为了阻止这种情况的发生,我在这里使用了这种方法,并在将第二个方法传递给列表之前,通过将调用更改SecondMethodSecondMethod(stockItems.ToList()


这解决了问题,但不会降低性能,是否有其他替代解决方案?
Dheeraj Kumar

0

首先,支持(至少)alsami的答案。那使我走上了正确的道路。

但对于那些进行IoC的人来说,这里有一些更深层次的探索。

我的错误(与其他错误相同)

发生一个或多个错误。(在上一个操作完成之前,第二个操作在此上下文上开始。这通常是由使用相同DbContext实例的不同线程引起的。有关如何避免DbContext出现线程问题的更多信息,请参见 https://go.microsoft.com。 / fwlink /?linkid = 2097913。

我的代码设置。“只是基础” ...

public class MyCoolDbContext: DbContext{
    public DbSet <MySpecialObject> MySpecialObjects {        get;        set;    }
}

public interface IMySpecialObjectDomainData{}

和(注意正在注入MyCoolDbContext)

public class MySpecialObjectEntityFrameworkDomainDataLayer: IMySpecialObjectDomainData{
    public MySpecialObjectEntityFrameworkDomainDataLayer(MyCoolDbContext context) {
        /* HERE IS WHERE TO SET THE BREAK POINT, HOW MANY TIMES IS THIS RUNNING??? */
        this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);
    }
}

public interface IMySpecialObjectManager{}

public class MySpecialObjectManager: IMySpecialObjectManager
{
    public const string ErrorMessageIMySpecialObjectDomainDataIsNull = "IMySpecialObjectDomainData is null";
    private readonly IMySpecialObjectDomainData mySpecialObjectDomainData;

    public MySpecialObjectManager(IMySpecialObjectDomainData mySpecialObjectDomainData) {
        this.mySpecialObjectDomainData = mySpecialObjectDomainData ?? throw new ArgumentNullException(ErrorMessageIMySpecialObjectDomainDataIsNull, (Exception)null);
    }
}

最后,从控制台应用程序(命令行界面应用程序)调用我的多线程类

    public interface IMySpecialObjectThatSpawnsThreads{}

public class MySpecialObjectThatSpawnsThreads: IMySpecialObjectThatSpawnsThreads
{
    public const string ErrorMessageIMySpecialObjectManagerIsNull = "IMySpecialObjectManager is null";

    private readonly IMySpecialObjectManager mySpecialObjectManager;

    public MySpecialObjectThatSpawnsThreads(IMySpecialObjectManager mySpecialObjectManager) {
        this.mySpecialObjectManager = mySpecialObjectManager ?? throw new ArgumentNullException(ErrorMessageIMySpecialObjectManagerIsNull, (Exception)null);
    }
}

和DI的积累。(同样,这是针对控制台应用程序(命令行界面)的……其行为与网络应用程序略有不同)

private static IServiceProvider BuildDi(IConfiguration configuration) {
    /* this is being called early inside my command line application ("console application") */

    string defaultConnectionStringValue = string.Empty; /* get this value from configuration */

    ////setup our DI
    IServiceCollection servColl = new ServiceCollection()
        ////.AddLogging(loggingBuilder => loggingBuilder.AddConsole())

        /* THE BELOW TWO ARE THE ONES THAT TRIPPED ME UP.  */
        .AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
    .AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()

    /* so the "ServiceLifetime.Transient" below................is what you will find most commonly on the internet search results */
     # if (MY_ORACLE)
        .AddDbContext<ProvisioningDbContext>(options => options.UseOracle(defaultConnectionStringValue), ServiceLifetime.Transient);
     # endif

     # if (MY_SQL_SERVER)
        .AddDbContext<ProvisioningDbContext>(options => options.UseSqlServer(defaultConnectionStringValue), ServiceLifetime.Transient);
     # endif

    servColl.AddSingleton <IMySpecialObjectThatSpawnsThreads,        MySpecialObjectThatSpawnsThreads>();

    ServiceProvider servProv = servColl.BuildServiceProvider();

    return servProv;
}

令我惊讶的是

        .AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
    .AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()

注意,我认为是因为将IMySpecialObjectManager注入到“ MySpecialObjectThatSpawnsThreads”中,所以这些注入的对象需要是Transient才能完成链。

关键是.........不仅需要。瞬变的(My)DbContext,还需要更大的DI图块。

调试提示:

这行:

this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);

将调试器断点放在此处。如果您的MySpecialObjectThatSpawnsThreads正在创建N个线程(例如10个线程)……而该行仅被命中一次……那是您的问题。您的DbContext正在穿越线程。

奖金:

我建议阅读下面的url / article(老歌,但好东西),了解网络应用和控制台应用之间的差异

https://mehdi.me/ambient-dbcontext-in-ef6/

如果链接发生更改,这是文章的标题。

使用实体框架正确管理DBCONTEXT 6:深入指南Mehdi El Gueddari

我用WorkFlowCore https://github.com/danielgerlag/workflow-core碰到了这个问题

  <ItemGroup>
    <PackageReference Include="WorkflowCore" Version="3.1.5" />
  </ItemGroup>

下面的示例代码..以帮助将来的互联网搜索者

 namespace MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Workflows
    {
        using System;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Constants;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Glue;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.WorkflowSteps;

        using WorkflowCore.Interface;
        using WorkflowCore.Models;

        public class MySpecialObjectInterviewDefaultWorkflow : IWorkflow<MySpecialObjectInterviewPassThroughData>
        {
            public const string WorkFlowId = "MySpecialObjectInterviewWorkflowId";

            public const int WorkFlowVersion = 1;

            public string Id => WorkFlowId;

            public int Version => WorkFlowVersion;

            public void Build(IWorkflowBuilder<MySpecialObjectInterviewPassThroughData> builder)
            {
                builder
                             .StartWith(context =>
                    {
                        Console.WriteLine("Starting workflow...");
                        return ExecutionResult.Next();
                    })

                        /* bunch of other Steps here that were using IMySpecialObjectManager.. here is where my DbContext was getting cross-threaded */


                    .Then(lastContext =>
                    {
                        Console.WriteLine();

                        bool wroteConcreteMsg = false;
                        if (null != lastContext && null != lastContext.Workflow && null != lastContext.Workflow.Data)
                        {
                            MySpecialObjectInterviewPassThroughData castItem = lastContext.Workflow.Data as MySpecialObjectInterviewPassThroughData;
                            if (null != castItem)
                            {
                                Console.WriteLine("MySpecialObjectInterviewDefaultWorkflow complete :)  {0}   -> {1}", castItem.PropertyOne, castItem.PropertyTwo);
                                wroteConcreteMsg = true;
                            }
                        }

                        if (!wroteConcreteMsg)
                        {
                            Console.WriteLine("MySpecialObjectInterviewDefaultWorkflow complete (.Data did not cast)");
                        }

                        return ExecutionResult.Next();
                    }))

                    .OnError(WorkflowCore.Models.WorkflowErrorHandling.Retry, TimeSpan.FromSeconds(60));

            }
        }
    }

ICollection<string> workFlowGeneratedIds = new List<string>();
                for (int i = 0; i < 10; i++)
                {
                    MySpecialObjectInterviewPassThroughData currentMySpecialObjectInterviewPassThroughData = new MySpecialObjectInterviewPassThroughData();
                    currentMySpecialObjectInterviewPassThroughData.MySpecialObjectInterviewPassThroughDataSurrogateKey = i;

                    ////  private readonly IWorkflowHost workflowHost;
                    string wfid = await this.workflowHost.StartWorkflow(MySpecialObjectInterviewDefaultWorkflow.WorkFlowId, MySpecialObjectInterviewDefaultWorkflow.WorkFlowVersion, currentMySpecialObjectInterviewPassThroughData);
                    workFlowGeneratedIds.Add(wfid);
                }

0

就我而言,我在Blazor中使用模板组件。

 <BTable ID="Table1" TotalRows="MyList.Count()">

问题是在组件标头中调用方法(计数)。为了解决这个问题,我将其更改为:

int total = MyList.Count();

然后 :

<BTable ID="Table1" TotalRows="total">

0

我知道这个问题已经在两年前问过了,但是我刚刚遇到了这个问题,我使用的修复程序确实有所帮助。

如果您要使用相同的上下文执行两个查询,则可能需要删除AsNoTracking。如果您确实使用过AsNoTracking,则每次读取都会创建一个新的数据读取器。两个数据读取器无法读取相同的数据。


0

就我而言,我使用的锁不允许您使用await,并且在您不等待异步时也不会创建编译器警告。

问题:

lock (someLockObject) {
    // do stuff
    context.SaveChangesAsync();
}

// some other code somewhere else doing await context.SaveChangesAsync() shortly after the lock gets the concurrency error

解决方法:通过使用.Wait()阻止它来等待锁内的异步

lock (someLockObject) {
    // do stuff
    context.SaveChangesAsync().Wait();
}

0

另一种可能的情况:如果您直接使用连接,请不要忘记关闭if。我需要执行任意SQL查询,并读取结果。这是一个快速解决方案,我不想定义数据类,也不想设置“普通” SQL连接。因此,我简单地将EFC的数据库连接重用为var connection = Context.Database.GetDbConnection() as SqlConnection。确保connection.Close()先打电话给您Context.SaveChanges()


-1

当我尝试FirstOrDefaultAsync() 在下面的代码中的异步方法中使用时,我遇到了同样的问题 。当我FirstOrDefault()解决问题时,问题就解决了!

_context.Issues.Add(issue);
        await _context.SaveChangesAsync();

        int userId = _context.Users
            .Where(u => u.UserName == Options.UserName)
            .FirstOrDefaultAsync()
            .Id;
...

1
它与FirstOrDefault()或FirstOrDefaultAsync()完全无关,它与dbContext的用法有关。
sajadre

-2

如果您的方法正在返回某些内容,则可以通过将其.Result放到工作的末尾 .Wait()并且不返回任何内容来解决此错误 。


-6

我只是设法使其再次起作用。这没有多大意义,但是它起作用了:

  1. 从StartUp删除Hangfire(我在那创建工作)
  2. 删除了hangfire数据库
  3. 重新启动服务器

我将在以后进行进一步研究,但是我用hangfire调用的方法收到一个DBContext,这可能是原因。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.