есть табличка "Table", содержащая поля [a1, a2, a3], по которым построен индекс. необходимо реализовать метод для выборки записей из данной таблички по указанным полям:
где Key — дополнительная вспомогательная структура:
class Key
{
public a1 {get;}
public a2 {get;}
public a3 {get;}
}
получается что-то вроде:
IEnumerable<Table> FindRecords(DataContext dc, IEnumerable<Key> keys)
{
var q = from t in dataContext.Table
from key in keys
where t.a1 == key.a1 && t.a2 == key.a2 && t.a3 == key.t3
select t;
return q;
}
Это компилируется, однако при обращении в самим данным вылетает эксепшин:
An unhandled exception of type 'System.NotSupportedException' occurred in System.Data.Linq.dll
Additional information: Local sequence cannot be used in LINQ to SQL implementations of query operators except the Contains operator.
ОК подсунул ему Contains
IEnumerable<Table> FindRecords(DataContext dc, IEnumerable<Key> keys)
{
var q = from t in dataContext.Table
from key in keys
where keys.Contains(makeKey(t.a1, t.a2, t.a3))
select t;
return q;
}
Cообщение об ошибке не изменилось...
Подскажите, существует ли возможность реализовать метод FindRecords с указанной выше сигнатурой, учитывая что таблица содержит большое количество данных, тоесть необходимо заставить использоваться индекс для [a1, a2, a3]?
Пока вижу только два варианта, но оба "левые":
1. заполнять временную табличку с ключами и её джоинить c "Table"
2. выбирать построчно, тоесть что-то вроде:
Здравствуйте, Angler, Вы писали:
A>Всем привет, A>Cообщение об ошибке не изменилось... A>Подскажите, существует ли возможность реализовать метод FindRecords с указанной выше сигнатурой, учитывая что таблица содержит большое количество данных, тоесть необходимо заставить использоваться индекс для [a1, a2, a3]? A>Пока вижу только два варианта, но оба "левые": A>1. заполнять временную табличку с ключами и её джоинить c "Table" A>2. выбирать построчно, тоесть что-то вроде:
В запросах LINQ2SQL нельзя мешать источники данных из DataContext и из локальных списков, так как линк2sql транслирует запросы в SQL, который о локальных данных ничего не знает.
Если данных в keys у вас не очень много, то второй вариант вполне подходит.
Шурыгин Сергей
"Не следует преумножать сущности сверх необходимости" (с) Оккам
Здравствуйте, Sshur, Вы писали:
S>В запросах LINQ2SQL нельзя мешать источники данных из DataContext и из локальных списков, так как линк2sql транслирует запросы в SQL, который о локальных данных ничего не знает.
Вообще-то это не совсем верно, т.к. Contains с локальной коллекцией прекрасно работает.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Sshur, Вы писали:
S>>В запросах LINQ2SQL нельзя мешать источники данных из DataContext и из локальных списков, так как линк2sql транслирует запросы в SQL, который о локальных данных ничего не знает.
L>Вообще-то это не совсем верно, т.к. Contains с локальной коллекцией прекрасно работает.
Ну да, я имел в виду, что в Join нельзя смешивать. Про Contains on и сам в ошибке пишет, что можно.
Шурыгин Сергей
"Не следует преумножать сущности сверх необходимости" (с) Оккам
Здравствуйте, Angler, Вы писали:
A>Пока вижу только два варианта, но оба "левые": A>1. заполнять временную табличку с ключами и её джоинить c "Table" A>2. выбирать построчно, тоесть что-то вроде:
3-й левый:
В цикле посроить IQueriable<Table>. Что-то типа
var queries = from key in keys
select
(from t in dataContext.Table
where t.a1 == key.a1 && t.a2 == key.a2 && t.a3 == key.t3
select t);
var query = queries.Aggregate((q1, q2) => q1.Union(q2));
По идее должно работать. Правда, не уверен на счет того, насколько эффективно будет в плане перформанса.
L>По идее должно работать. Правда, не уверен на счет того, насколько эффективно будет в плане перформанса.
Генерируется один мега-запросище, но какой
select ...
from
(
select ...
from
(
select ...
from
(
select ...
from
(
-- и так далее для всех вариантов keys
)
union
select ...
from
)
union
select ...
from
)
union
select ...
from
)
Спасибо, это то, что я хотел. Одно только напрягает — ограничение на количество параметров в запросе. Тоесть прийдётся ещё входящую коллекцию keys бить на порции при таком подходе.
Здравствуйте, Angler, Вы писали:
L>>По идее должно работать. Правда, не уверен на счет того, насколько эффективно будет в плане перформанса.
A>Генерируется один мега-запросище, но какой
Гы-гы. А если план посмотреть?
Кстати, этот "ужас-ужас" можно упростить до просто "ужаса", если делать union более хитро, разбивая на группы по двое.
Здравствуйте, Angler, Вы писали:
A>Здравствуйте, ksg71, Вы писали:
K>>Здравствуйте, Angler, Вы писали:
K>>как вариант, стройте предикат динамически
A>Спасибо, это то, что я хотел. Одно только напрягает — ограничение на количество параметров в запросе. Тоесть прийдётся ещё входящую коллекцию keys бить на порции при таком подходе.
Какое ограничение?
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Здравствуйте, ksg71, Вы писали:
K>Здравствуйте, Angler, Вы писали:
A>>Здравствуйте, ksg71, Вы писали:
K>>>Здравствуйте, Angler, Вы писали:
K>>>как вариант, стройте предикат динамически
A>>Спасибо, это то, что я хотел. Одно только напрягает — ограничение на количество параметров в запросе. Тоесть прийдётся ещё входящую коллекцию keys бить на порции при таком подходе.
K>Какое ограничение?
1024 параметра в SQL запросе? ну как бы да
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?
Шурыгин Сергей
"Не следует преумножать сущности сверх необходимости" (с) Оккам
+ еще и строго-типизированно. Чего еще для счастья надо?
L>>Кстати, этот "ужас-ужас" можно упростить до просто "ужаса", если делать union более хитро, разбивая на группы по двое.
A>тоесть в одном подзапросе возвращать сразу две записи?
Нет, имелось в виду, разбивать ключи на две примерно равные группы, по кажной группе строить запрос и union-ить уже эти запросы.
Здравствуйте, Sshur, Вы писали:
S>Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?
И что с ней дальше делать? Формировать запрос динамически? Дык это ничуть не легче, чем сформировать динамически нужный expression.
Здравствуйте, Sshur, Вы писали:
S>Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?
Кстати, сли развить эту идею, то можно замутить гибридный вариант:
1. Завести в sqlserver-е функцию, принимающую xml и через OPENXML возвращающую табличку с нужной структурой.
2. Добавить эту функцию в datacontext.
3. Использовать функцию в запросе, передавая в кач-ве параметра сериализованную коллекцию ключей.
Нет возможности проверить, но по идее должно работать.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Sshur, Вы писали:
S>>Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?
L>И что с ней дальше делать? Формировать запрос динамически? Дык это ничуть не легче, чем сформировать динамически нужный expression.
Варианта два, либо разобрать строку, сохранить во временную таблицу и потом сджойнить её с искомой, либо сделать xml и воспользовать OPENXML.
Можно ещё хранимку на .net написать. Это я думаю будет самым быстрым.
Шурыгин Сергей
"Не следует преумножать сущности сверх необходимости" (с) Оккам