Linq to SQL проблема - PullRequest
       28

Linq to SQL проблема

4 голосов
/ 26 марта 2010

У меня есть локальная коллекция идентификаторов записей (целых чисел).

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

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

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;

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

Локальная последовательность не может использоваться в реализации операторов запросов Linq to SQL, кроме оператора Contains ().

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

Ответы [ 5 ]

1 голос
/ 26 марта 2010

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

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

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

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;

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

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 server будет barf на количество параметров.

1 голос
/ 26 марта 2010

то, что говорит компилятор ...

OwnerIds.Contains(someVariable)

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

WHERE someVariable IN (OwnerId1, OwnerId2, OwnerIdN)

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

1 голос
/ 26 марта 2010

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

При использовании прямого SQL вы можете использовать для этого обычный оператор SELECT с оператором in (). (не входите более 1000 наименований в "в")

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

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

0 голосов
/ 26 марта 2010

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

1) загрузить ВСЕ строки отфильтрованного патча из SQL

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

2) фильтровать данные как простую локальную последовательность

var result = loadedData.Where(i => i.PatchesOwners.All(o => OwnerIds.Contains(o.ID)));
0 голосов
/ 26 марта 2010

Не могли бы вы присоединиться к OwnerIds?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...