Entity Framework Core: вторая операция началась в этом контексте до завершения предыдущей операции

89

Я работаю над проектом ASP.Net Core 2.0 с использованием Entity Framework Core

<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
И чтобы узнать, включены ли несколько активных результатов
Джей,
Столкнувшись с той же проблемой, я обнаружил, что в моей таблице базы данных есть целые числа, допускающие значение NULL. как только я установил для свойств модели сущности соответствие int, допускающее значение NULL, все заработало, поэтому сообщения вводили меня в заблуждение ...!
AlwaysLearning

Ответы:

87

Я не уверен, используете ли вы IoC и Dependency Injection для разрешения своего DbContext, где бы он ни был. Если вы это делаете, и вы используете собственный IoC из .NET Core (или любого другого IoC-контейнера) и получаете эту ошибку, обязательно зарегистрируйте свой DbContext как Transient. Делать

services.AddTransient<MyContext>();

ИЛИ

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

вместо того

services.AddDbContext<MyContext>();

AddDbContext добавляет контекст как ограниченный, что может вызвать проблемы при работе с несколькими потоками.

Также операции async / await могут вызывать это поведение при использовании асинхронных лямбда-выражений.

Добавление его как переходного процесса также имеет свои недостатки. Вы не сможете вносить изменения в какую-либо сущность в нескольких классах, использующих контекст, потому что каждый класс получит свой собственный экземпляр вашего DbContext.

Простое объяснение этому состоит в том, что DbContextреализация не является потокобезопасной. Вы можете прочитать об этом здесь

Alsami
источник
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
3
Как указывалось ранее, если вы пропустите вызов асинхронного метода с ключевым словом await, вы столкнетесь с этой проблемой.
Йеннифер 05
1
Это может быть нормально, но нужно более внимательно относиться к желаемому времени жизни и разрешению доступа к данным, чем к бесцеремонному использованию переходного процесса без нюансов обстоятельств. Фактически, я считаю редким, что кому-то может понадобиться временный контекст данных. Если объем единицы работы включает в себя более одной операции с данными, объем транзакции должен охватывать больше. Разрешение контекста данных должно отражать объем вашей единицы работы. Это то, что следует продумать, и это не универсальный ответ.
Дэйв Раэль
3
@alsami ты мой герой. 6 часов мучительной отладки. Это было решение. Если кто-то еще вводит IHttpContextAccessor в DbContext, а утверждения равны нулю, это решение. Большое спасибо, чувак.
jcmontx
56

В некоторых случаях эта ошибка возникает при вызове асинхронного метода без awaitключевого слова, что можно просто решить, добавив его awaitперед вызовом метода. однако ответ может не иметь отношения к упомянутому вопросу, но может помочь решить аналогичную ошибку.

Хамид Насирлоо
источник
4
Это случилось со мной. Переход First()на работу await / FirstAsync().
Гильерме
Голосовать за. Также см. Jimlynn.wordpress.com/2017/11/16/… Джим Линн «ОШИБКА Фреймворка ENTITY: В ЭТОМ КОНТЕКСТЕ НАЧАЛАСЬ ВТОРАЯ ОПЕРАЦИЯ. ПЕРЕД ЗАВЕРШЕНИЕМ ПРЕДЫДУЩЕЙ ОПЕРАЦИИ. ЛЮБЫЕ ЧЛЕНЫ ИНСТАНЦИИ НЕ ГАРАНТИРУЮТСЯ БЕЗОПАСНОСТИ НИТИ».
granadaCoder
Спасибо за это! Это и была моя проблема ... Забыл добавить ожидание в асинхронный метод.
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 = await _context.Item.Where (x => x.OrderId == orderId) .ToListAsync (); возврат товаров; }
NMathur
@NMathur Выглядит нормально. Просто убедитесь, что вы всегда используете awaitасинхронные методы. Если вы не используете await, вы можете непреднамеренно попасть в многопоточность.
Габриэль Люси,
8
  • Решите мою проблему, используя эту строку кода в моем файле Startup.cs.
    Добавление временной службы означает, что каждый раз, когда служба запрашивается, создается новый экземпляр, когда вы работаете с внедрением зависимостей.

           services.AddDbContext<Context>(options =>
                            options.UseSqlServer(_configuration.GetConnectionString("ContextConn")),
                 ServiceLifetime.Transient);
    
Мухаммад Армаган
источник
6

У меня была такая же проблема, и оказалось, что родительская служба была одиночкой. Так что контекст тоже автоматически стал синглтоном. Хотя он был объявлен как Per Life Time Scoped в DI.

Внедрение службы с разными сроками жизни в другую

  1. Никогда не вставляйте службы Scoped & Transient в службу Singleton. (Это эффективно преобразует временную или ограниченную службу в синглтон.)

  2. Никогда не вводите временные службы в службу с заданной областью (это преобразует временную службу в службу с заданной областью).

DiPix
источник
именно это и была моя проблема
Jonesopolis
Это тоже была моя проблема. Я регистрировал класс обработчика как одноэлементный, а DbContext как временный. Мне пришлось использовать ServiceProvider в классе Handler, чтобы получать временный экземпляр из контейнера DI каждый раз при срабатывании Handler
Дайана Содре
5

У меня была такая же ошибка. Это произошло потому, что я вызвал метод, построенный как public async void ...вместо public async Task ....

Raynlaze
источник
4

Я думаю, что этот ответ еще может кому-то помочь и сэкономить много раз. Я решил аналогичную проблему, перейдя IQueryableна List(или на массив, коллекцию ...).

Например:

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

к

var list=_context.table1.where(...).ToList(); //or ToArray()...
Махиди Масимов
источник
2
ИМХО, этот ответ не заслуживает минусовых баллов, просто плохо выражен. .ToList () действительно решает большинство проблем «второй операцией ...» из-за того, что заставляет немедленное вычисление выражения. Таким образом, отсутствуют контекстные операции очереди.
vassilag
Это было проблемой в моем случае. У меня было xxx.Contains (z.prop) в предложении where запроса. 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

Entity Framework Core не поддерживает выполнение нескольких параллельных операций в одном 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 или класса модели в некоторых случаях. Сообщение об ошибке вводит в заблуждение. Первоначальное значение этого сообщения заключается в том, что вы не можете вызывать async для одного и того же 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.

NiPfi
источник
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();
}

Для того, чтобы остановить это происходит я использовал подход здесь и материализованные этот список , прежде чем передать его второй метод, изменяя вызов SecondMethodбудетSecondMethod(stockItems.ToList()

TomRedox
источник
Это решило проблему, но не снизит ли это производительность. Есть ли альтернативное решение?
Дирадж Кумар
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», эти внедренные объекты должны были быть временными для завершения цепочки.

Дело в том, что ....... не только (My) DbContext нуждался в .Transient ..., но и в большей части DI Graph.

Совет по отладке:

Эта строка:

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

Поместите там точку останова отладчика. Если ваш MySpecialObjectThatSpawnsThreads создает количество потоков N (например, 10 потоков) ... и эта строка используется только один раз ... это ваша проблема. Ваш DbContext пересекает потоки.

БОНУС:

Я бы посоветовал прочитать ниже URL / статью (старая, но хорошая) о различиях веб-приложений и консольных приложений.

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

Заголовок статьи на случай, если ссылка изменится.

ПРАВИЛЬНОЕ УПРАВЛЕНИЕ DBCONTEXT С ENTITY FRAMEWORK 6: ГЛУБОКОЕ РУКОВОДСТВО Мехди Эль Геддари

Я столкнулся с этой проблемой с помощью 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);
                }
GranadaCoder
источник
0

В моем случае я использую компонент шаблона в Blazor.

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

Проблема заключается в вызове метода (Count) в заголовке компонента. Чтобы решить проблему, я изменил его так:

int total = MyList.Count();

и позже :

<BTable ID="Table1" TotalRows="total">
Али Борджян
источник
0

Я знаю, что эту проблему задали два года назад, но у меня только что возникла эта проблема, и исправление, которое я использовал, действительно помогло.

Если вы выполняете два запроса с одним и тем же контекстом - вам может потребоваться удалить AsNoTracking. Если вы все же используете, AsNoTrackingвы создаете новый считыватель данных для каждого чтения. Два считывателя данных не могут читать одни и те же данные.

Корнелис де Ягер
источник
0

В моем случае я использовал блокировку, которая не позволяет использовать await и не создает предупреждение компилятора, когда вы не ожидаете async.

Проблема:

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() метод async в приведенном ниже коде. А когда починил FirstOrDefault()- проблема решилась!

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

        int userId = _context.Users
            .Where(u => u.UserName == Options.UserName)
            .FirstOrDefaultAsync()
            .Id;
...
JuSik404
источник
1
Это никак не связано с FirstOrDefault () или FirstOrDefaultAsync (), а связано с использованием dbContext.
sajadre
-2

Если ваш метод что-то возвращает, вы можете решить эту ошибку, .Resultзавершив задание и .Wait()ничего не вернув .

Hasan_H
источник
-6

Мне просто удалось заставить его снова работать. В этом нет особого смысла, но это сработало:

  1. Удалите Hangfire из StartUp (я там создавал свою работу)
  2. Удалил базу данных Hangfire
  3. Перезапустил сервер

Позже я займусь этим дальше, но метод, который я вызвал с помощью hangfire, получает DBContext, и это возможная причина.

Андре Луис
источник