Мы используем Entity Framework 6 и запрашиваем базу данных с помощью async.
У нас также есть интеграционный тест, запускающий код и для которого мы установили;
- Тест выполняетсяв транзакции, т. е. мы начинаем наш запуск с begin и заканчиваем его откатом
- . Данные устанавливаются перед запросами
- Все они выполняются для одного и того же dbContext
- IsolationLevelустановлено значение ReadUncommitted
Код:
var table1Id = await _dbContext.Table1.Where(x => x.IdentificationNumber == identificationNumber)
.Select(y => y.Id)
.SingleOrDefaultAsync().ConfigureAwait(false);
var table2Id = await _dbContext.Table2.Where(y => y.Table1Id == table1Id)
.Select(y => y.Id)
.FirstOrDefaultAsync().ConfigureAwait(false);
//Code continues...
При чтении базы данных в SSMS с использованием T-SQL и подсказка NOLOCK
показывает данные в таблицах.
Запуск моего кода выполняет оба запроса;первый выполняется правильно и возвращает table1Id, как и ожидалось, НО второй не возвращает никакого значения.Похоже, что не работает звонить дважды подряд?Если я переключу порядок, это будет table1Id, который не будет инициирован ни с каким значением.
Если я не использую async / await, то это тоже работает.
У кого-нибудь есть хорошее объяснение этому поведению?Я делаю это неправильно?
РЕДАКТИРОВАТЬ:
public async Task<List<Table4>> GetTable4ListAsync(string key)
{
var table1Id = await _dbContext.Table1.Where(x => x.Status == Status.Ready)
.OrderByDescending(x => x.Id).Select(y => y.Id).FirstOrDefaultAsync().ConfigureAwait(false);
//more code...
var table2Id = await _dbContext.Table2.Where(x => x.Key == key).Select(y => y.Id)
.SingleOrDefaultAsync()
.ConfigureAwait(false);
var table3Id = await _dbContext.Table3
.Where(y => y.Table2Id == table2Id &&
y.Table1Id == table1Id)
.Select(y => y.Id).FirstOrDefaultAsync().ConfigureAwait(false);
//more code...
var result = await _dbContext.Table4
.Where(x => x.Table3.Id == table3Id).ToListAsync()
.ConfigureAwait(false);
return result;
}
Выше код близок к нашему фактическому коду.
Когда код выполняется винтеграционный тест внутри транзакции;
- запуск транзакции
- настройка тестовых данных
- запуск теста
- откат транзакции
На шаге 3 только первый запрос возвращает результат независимо от порядка.
- Использование уровня изоляции ReadUncommitted
- Использование TransactionScopeAsyncFlowOption включено