Как я могу сжать следующий запрос Linq в один IQueryable - PullRequest
1 голос
/ 19 октября 2010

У меня есть модель EntityFramework, в которой есть сущность «Пользователь» с коллекцией организаций.

Для конкретного пользователя я пытаюсь написать запрос Linq для возврата названий организаций, которым принадлежит пользователь, гдезапрос попадет в базу данных только один раз.

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

То, что у меня есть до сих пор:

var orgNames = context.Users
    .Where(u => u.LoweredUserName == userName.ToLower())
    //materialises user
    .FirstOrDefault()
    .Organisations
    //second hit to the db
    .Select(o => o.Name);

К чему я стремился, но не вижу дрова для деревьев:

orgNames = context.Users
    .Where(u => u.LoweredUserName == userName.ToLower())
    //don't materialise but leave as IQueryable
    .Take(1)
    //The problem: turn what the query sees as possibly multiple
    // (due to the Take method) EntityCollection<Organisation> into a List<String>
    .Select(u => u.Organisations.Select(o => o.Name));

Я посмотрел на совокупности, но я, кажется, иду по кругу:)

Ответы [ 2 ]

2 голосов
/ 19 октября 2010

Doh!Я думаю, что могу ответить на свой вопрос, используя SelectMany, чтобы собрать коллекцию в одну коллекцию следующим образом:

orgNames = context.Users.Where(u => u.LoweredUserName == userName.ToLower())
                .Take(1)
                .SelectMany(u => u.Organisations)
                .Select(o => o.Name);
0 голосов
/ 19 октября 2010

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

context.Users
       .Where(u => u.LoweredUserName == userName.ToLower())
       .Select(u => u.Organisations.Select(o => o.Name));
...