В таблице я реализовал триггер базы данных для заполнения столбца вычисленным значением (столбец имеет имя ProjectCode
). Я использую контроллеры веб-API для создания и извлечения записей из базы данных. Экземпляр моего DbContext
вводится в контроллер.
Когда DbContext
добавляет новый экземпляр сущности, а затем сохраняет его, возвращаемые данные не включают автоматически созданное значение для столбца. База данных показывает правильное значение в столбце для вновь вставленной строки. Даже при получении данных одним и тем же методом свойство показывает значение null.
Project project = new Project();
dbContext.Projects.Add(project);
await dbContext.SaveChangesAsync();
// When placing a debugger stop here, and checking the database, I can see that the value for ProjectCode is populated correctly by the database trigger
// project.Id has valid value, however project.ProjectCode is null
Project createdProject = await dbContext.SingleOrDefaultAsync(p => p.Id == project.Id);
// createdProject is not null, however createdProject.ProjectCode is null
После завершения веб-вызова и удаления контроллера и DbContext
выполняется новый вызов веб-API для получения данных. DbContext
используется таким же образом при вызове
await dbContext.SingleOrDefaultAsync(p => p.Id == project.Id)
ProjectCode
тогда показывает, что он заполнен правильно.
Почему после добавления или немедленного извлечения он не отображается правильно, даже если строка в базе данных показывает, что она заполнена?
@topsail, спасибо, очень приятно это знать, на самом деле мы все еще застряли на версии 6. Однако знание об изменении полезно для нашего обновления!
Триггеры основаны на событиях. Таким образом, они выполняются на основе асинхронного события и не блокируют операцию, вызвавшую его выполнение.
Триггер, отвечающий на операцию вставки, выполняется после завершения вставки.
Я не уверен, как именно Entity Framework загружает обновленные значения, но это будет в одной транзакции, поэтому вы читаете только данные, которые были предоставлены во время этой транзакции, содержащей операцию вставки. (По умолчанию вы читаете зафиксированные данные)
Вы можете попытаться перезагрузить данные, хранящиеся в DbContext, вызвав
dbContext.Entry(project).ReloadAsync();
для обновления значений DbContext
вместо запроса по его идентификатору. (В конце концов, возможно, ничего не изменится, но будет более понятно, что вы пытаетесь сделать).
Связанная информация:
СОЗДАТЬ ТРИГГЕР (Transact-SQL)
Метод EntityEntry.ReloadAsync(CancellationToken)
Хм триггеры бывают блокирующие и синхронные.
Ладно, моя вина. Триггеры синхронны, но события не возникают синхронно.
Чего именно вы пытаетесь достичь? Вы не можете заранее рассчитать код проекта? Последовательность HILO не поможет?
Triggers are event based.
- нет, это неправда, триггеры запускаются в контексте той же транзакции, что и вставка/обновление/удаление и блокировка, и все или ничего, если триггер не работает, вставка/обновление/удаление завершается неудачно.
Более вероятный ответ заключается в том, что EF не ожидает изменения других значений, о которых он не знает, и поэтому не перечитывает данные. Вероятно, существует настройка, которая в таком случае заставит EF перечитать всю строку.
Если у вас есть вычисляемый столбец, вы можете настроить EF Core так, чтобы он всегда получал этот столбец, не допуская его использования в операциях INSERT и UPDATE:
modelBuilder.Entity<Project>()
.Property(e => e.ProjectCode)
.ValueGeneratedOnAddOrUpdate();
Это сработало, как и ожидалось, и реализовать было интуитивно понятно.
Ссылка: Learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/…