2013-10-12 3 views
9

Я использую Ef6 и хочу сделать следующий запрос полностью асинхронен:Как асинхронно вызывать базу данных с субрекциями с использованием LINQ?

await MyDataContext.ADbSet. 
        First(a => a.Something == "Something"). 
        ASubCollection. 
        Select(x => new { x.SubCollectionId }). 
        ToListAsync(); 

Это не работает, я считаю, из-за First() возвращение реального объекта и доступа к ASubCollection будучи ICollection, не IQueryable ,

я смог обойти это с помощью следующего кода:

await MyDataContext.ADbSet. 
        Where(a => a.Something == "Something"). 
        SelectMany(a => a.ASubCollection). 
        Select(x => new { x.SubCollectionId }). 
        ToListAsync(); 

Однако, это, кажется, «Hacky», как я использую Where(...), когда я должен использовать в First(), как я знаю, что во время компиляции что будет только один элемент, удовлетворяющий запросу. Есть ли лучший способ сделать это?

+2

Попробуйте '.Take (1)'. – Vladimir

+0

@ Владымир Фролов в какой момент? Пожалуйста, дополните. – Alex

+0

'.ADbSet.Where (a => a.Something ==« Что-то »). Возьмите (1)' – Vladimir

ответ

7

Вызов First() является вызовом, который фактически перечисляет базовую последовательность и возвращает объект вместо Task. Таким образом, First() не будет работать вместе с ключевым словом await.

Ваше второе решение полностью допустимо (а не вообще «взломано») в этом контексте, потому что нет необходимости добавлять ограничение к сгенерированному запросу базы данных, так как Where(...) -call вернет ровно один элемент в этот специальный случай - с или без ограничения в запросе.

Если Where -call, скорее всего, вернет несколько элементов, или вы просто хотите убедиться, что будет рассмотрен только первый элемент, вставка вызова в Take(1) приведет к первому элементу последовательности, но все же будет :

await MyDataContext.ADbSet 
        .Where(a => a.Something == "Something") 
        .Take(1) 
        .SelectMany(a => a.ASubCollection) 
        .Select(x => new { x.SubCollectionId }) 
        .ToListAsync(); 
+0

Ну, это то, что Джоэл Спольский называет «утечкой абстракции» :) Спасибо за информацию! – DarkWanderer

+0

@DarkWanderer Кажется, вы правы в этом! :) Для тех, кто, как и я, может задаться вопросом, что такое «утечка абстракции», вот ссылка на блог Джоэла: [Закон липких абстракций] (http://www.joelonsoftware.com/articles/LeakyAbstractions.html) – Spontifixus