2013-07-17 4 views
3

У меня есть динамические поля внутри пользовательских групп, и я хочу выбрать их на основе того, что пользователь пользовательских групп.SelectMany делает слишком много запросов

В основном я хочу симулировать запрос, например, .Where(x => x.UserGroupId == x || ..., потому что в противном случае он составляет около 20 запросов, чтобы получить динамические поля.

Возможно, я могу как-то передать массив целых чисел как UserGroupId, и он будет имитировать запрос с помощью ||.

Вот мой пример, как выход результатов является таким же, только разница в том, что первые из них имеет 20 запросов к базе данных и вторым имеют только 1.

public IEnumerable<UserGroup> UserGroups 
{ 
    get 
    { 
     var db = new MainDataContext(); 
     return db.UserGroupUsers.Where(x => x.UserId == this.Id).Select(x => x.UserGroup); 
    } 
} 
public IEnumerable<UserDynamicField> DynamicFields 
{ 
    get 
    { 
     var db = new MainDataContext(); 

     var fields = this.UserGroups.SelectMany(x => x.UserGroupDynamicFields); // 20+ queries 

     var fields2 = db.UserGroupDynamicFields.Where(x => 
      x.UserGroupId == 1 || 
      x.UserGroupId == 2 || 
      x.UserGroupId == 3 || 
      x.UserGroupId == 4 || 
      x.UserGroupId == 5 || 
      x.UserGroupId == 6 || 
      x.UserGroupId == 7 || 
      x.UserGroupId == 8 || 
      x.UserGroupId == 9 || 
      x.UserGroupId == 10); // 1 query, maybe I can somehow pass array of Id's here? 
    } 
} 

ответ

2

Попробуйте преобразовать его в IQueryable<T> вместо IEnumerable<T>:

public IQueryable<UserGroup> UserGroups 
{ 
    get 
    { 
     var db = new MainDataContext(); 
     return db.UserGroupUsers.Where(x => x.UserId == this.Id) 
           .Select(x => x.UserGroup); 
    } 
} 
public IQueryable<UserDynamicField> DynamicFields 
{ 
    get 
    { 
     // 1 query 
     return this.UserGroups.SelectMany(x => x.UserGroupDynamicFields); 
    } 
} 

Это позволит Linq воспользоваться тем фактом, что он не должен тянуть набор результатов в памяти, пока она не итерация, так что это будет переведен на обычный SQL присоединиться.

+0

Черт! Это было легко, я думал, что это будет намного сложнее. Спасибо :) – sed

+1

@Steve Рад помочь. В общем случае, если вы оставите коллекцию как 'IQueryable ', любые выполняемые на ней Linq-методы запускаются в базе данных, в отличие от 'IEnumerble ', которые запускаются локально. Однако оба они используют ленивое исполнение, поэтому он не будет работать вообще, пока вы на самом деле не попытаетесь получить результаты. –

+0

Да, но 'DynamicFields' должен, вероятно, оставаться' IEnumerable', потому что он использует 'yield return', и я не могу использовать' IQueriable' с этим. – sed

Смежные вопросы