2010-03-26 3 views
4

У меня есть локальная коллекция записей Id (целые числа).Проблема Linq to SQL

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

Вот мой запрос:

public List<int> OwnerIds { get; private set; } 
... 
filteredPatches = from p in filteredPatches 
        where OwnerIds.All(o => p.PatchesOwners.Select(x => x.OwnerId).Contains(o)) 
        select p; 

Я получаю эту ошибку:

Local sequence cannot be used in Linq to SQL implementation of query operators except the Contains() operator.

Я понимаю, что .Вс() не поддерживается Linq к SQL, но есть способ делать то, что я пытаюсь сделать?

ответ

1

Клиенты, где OrderIds в дочерней коллекции являются подмножеством идентификаторов в коллекции в памяти.

from c in myDC.Customer 
where c.Orders.All(o => myList.Contains(o.ID)) 
select c; 

Клиенты где OrderIds в коллекции в памяти являются подмножеством идентификаторов в коллекции детской.

from c in myDC.Customers 
where (from o in c.Orders 
    where myList.Contains(o.ID) 
    group o.ID by o.ID).Distinct().Count() == myList.Count() 
select c; 

Клиентов где OrderIds в коллекции в-памяти идентификаторов в коллекции детской равно установленные.

from c in myDC.Customers 
let Ids = c.Orders.Select(o => o.ID).Distinct() 
where Ids.Count() == myList.Count() 
    && Ids.All(id => myList.Contains(id)) 
select c; 

Все эти сгенерированные sql для меня.

PS - они предполагают, что идентификаторы уже выделены в myList. Если они еще не введены, используйте:

myList = myList.Distinct().ToList(); 

PSS - подходит для списков до ~ 2000 единиц. Выше, чем это будет переведено в sql, а затем sql-сервер будет зависеть от количества параметров.

1

Я не знаю, как это сделать с Linq to SQL. Проблема в том, что вам нужно получить свой список на сервере, чтобы он мог запросить его. (ваш список находится в памяти на вашем компьютере, SQL Server должен выполнить фильтрацию на сервере)

С прямым SQL вы можете использовать регулярную инструкцию SELECT с оператором «in()» для этого. (не переходите более 1000 позиций в «in»)

Вы можете вставить все ID в временную таблицу в SQL, а затем присоединиться к таблице (вы можете использовать LINQ с этим решением, но для этого требуется 2 шага - вставка (при условии, что у вас есть таблица «sets»), а затем объединенный запрос (а затем запрос очистки для удаления вашего набора).

Вы можете запросить запрос LINQ без условия фильтра и затем фильтровать на своем (не рекомендуется, если нефильтрованный набор результатов может быть большим).

+0

"кроме оператора Содержит". –

+0

Также - почему бы не переместиться более 1000 предметов в «в»? Я делал это много раз без последствий. –

+0

@DavidB - не знал о операторе contains. Вот почему я сказал: «Я не знаю пути ...», вместо «нет». Что касается пересылки более 1000 предметов, которые мы фактически протестировали с этим, и обнаружили, что при некоторых обстоятельствах производительность вашего запроса будет погружаться. Если у вас более 1000 элементов, вы можете повысить производительность запросов, разбив их на 2 или более запросов. – JMarsch

0

Ошибка указана «Локальная последовательность (означает OwnerIds) не может использоваться в реализации операторов запроса Linq to SQL, за исключением Содержит оператор() « Так что вы можете сделать:.

1) загрузить ВСЕ filteredPatches строки из SQL

var loadedData = filteredPatches.Select(i => i).ToList(); 

2) фильтрации данных, как простая локальная последовательность

var result = loadedData.Where(i => i.PatchesOwners.All(o => OwnerIds.Contains(o.ID))); 
1

что говорит составитель это ...

OwnerIds.Contains(someVariable) 

поддерживается, и оно будет переведено как:

WHERE someVariable IN (OwnerId1, OwnerId2, OwnerIdN) 

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

+0

И если вы хотите проверить, что что-то есть в каждом списке, вы можете использовать 'not Any (not Contains (...))' –

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