В первом примере, если вы можете внести следующие изменения в оператор возврата:
return products.Where(p => p.Active).ToList();
, тогда будет работать как положено .
Дело 1:
Проблема здесь в том, что Where
предложение, применённое к IEnumerable<Product>
, является отложенным выполнением, которое возвращается в виде Task
в виде Task<IEnumerable<Product>>
, но теперь вам нужно запустить Task
, который должен выполнить предикат тоже. Не уверен, как вы выполняете задание, или, возможно, есть проблема с переносом отложенного выполнения таким образом, но конечный результат - предикат не вступает в силу, как ожидалось, даже когда он применяется к результату Dapper, что буферизируется по умолчанию (без потоковой передачи)
Дело 2:
Это работает во втором случае, так как вы полностью избавляетесь от отложенного выполнения, Enumerable.Empty<Product>()
гарантирует, что память будет выделена первой, поэтому предикат исполняется в момент его применения, когда отложенное выполнение не выполняется. Фактически предикат применяется любым способом вне блока using
.
В асинхронном методе вы удаляете соединение с помощью блока using
, в основном из-за того, что Dapper внутренне выделяет память, поэтому все данные передаются, соединение тогда disposed
, а предикат никогда не выполняется. У меня есть подобный пример, который не зависит от соединения с базой данных, и он работает, как и ожидалось, поэтому мы можем сделать вывод, что расположение соединения играет роль в предикате, который не выполняется. Во втором случае предикат применяется вне блока using
, поэтому удаление подключения не имеет роли, а память уже выделена.
Пример кода (с использованием LinqPad):
async Task Main()
{
var result = await GetTest();
result.Dump();
}
public async Task<IEnumerable<Test>> GetTest()
{
var value = await GetTestDb();
return value.Where(x => x.Id == 1);
}
public async Task<IEnumerable<Test>> GetTestDb()
{
return await Task.FromResult(
new List<Test>
{
new Test{Id = 1, Name = "M"},
new Test{Id = 2, Name = "S"}
}
);
}
public class Test
{
public int Id { get; set; }
public string Name { get; set; }
}
Результат: