linq2sql и локальные последовательности
От: Angler Россия  
Дата: 29.12.10 12:20
Оценка:
Всем привет,


есть табличка "Table", содержащая поля [a1, a2, a3], по которым построен индекс. необходимо реализовать метод для выборки записей из данной таблички по указанным полям:
IEnumerable<Table> FindRecords(DataContext dc, IEnumerable<Key> keys);

где 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. выбирать построчно, тоесть что-то вроде:

IEnumerable<Table> FindRecords(DataContext dc, IEnumerable<Key> keys)
{
   return keys
      .SelectMany(key => dataContext.Table.Where(t => t.a1 == key.a1 && t.a2 == key.a2 && t.a3 == key.t3));
}




Спасибо.
Re: linq2sql и локальные последовательности
От: ksg71 Германия  
Дата: 29.12.10 12:26
Оценка: 6 (1)
Здравствуйте, Angler, Вы писали:

как вариант, стройте предикат динамически
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re: linq2sql и локальные последовательности
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 29.12.10 12:31
Оценка:
Здравствуйте, Angler, Вы писали:

A>Всем привет,

A>Cообщение об ошибке не изменилось...
A>Подскажите, существует ли возможность реализовать метод FindRecords с указанной выше сигнатурой, учитывая что таблица содержит большое количество данных, тоесть необходимо заставить использоваться индекс для [a1, a2, a3]?
A>Пока вижу только два варианта, но оба "левые":
A>1. заполнять временную табличку с ключами и её джоинить c "Table"
A>2. выбирать построчно, тоесть что-то вроде:

В запросах LINQ2SQL нельзя мешать источники данных из DataContext и из локальных списков, так как линк2sql транслирует запросы в SQL, который о локальных данных ничего не знает.

Если данных в keys у вас не очень много, то второй вариант вполне подходит.
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[2]: linq2sql и локальные последовательности
От: Lloyd Россия  
Дата: 29.12.10 12:34
Оценка:
Здравствуйте, Sshur, Вы писали:

S>В запросах LINQ2SQL нельзя мешать источники данных из DataContext и из локальных списков, так как линк2sql транслирует запросы в SQL, который о локальных данных ничего не знает.


Вообще-то это не совсем верно, т.к. Contains с локальной коллекцией прекрасно работает.
Re[3]: linq2sql и локальные последовательности
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 29.12.10 12:38
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, Sshur, Вы писали:


S>>В запросах LINQ2SQL нельзя мешать источники данных из DataContext и из локальных списков, так как линк2sql транслирует запросы в SQL, который о локальных данных ничего не знает.


L>Вообще-то это не совсем верно, т.к. Contains с локальной коллекцией прекрасно работает.


Ну да, я имел в виду, что в Join нельзя смешивать. Про Contains on и сам в ошибке пишет, что можно.
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re: linq2sql и локальные последовательности
От: Lloyd Россия  
Дата: 29.12.10 12:53
Оценка: 6 (1)
Здравствуйте, 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));

По идее должно работать. Правда, не уверен на счет того, насколько эффективно будет в плане перформанса.
Re[2]: linq2sql и локальные последовательности
От: Angler Россия  
Дата: 29.12.10 13:12
Оценка:
Здравствуйте, Lloyd, Вы писали:


L>По идее должно работать. Правда, не уверен на счет того, насколько эффективно будет в плане перформанса.


Генерируется один мега-запросище, но какой

select ... 
from
(
  select ... 
  from
  (
    select ... 
    from
    (
      select ... 
      from
      (
        -- и так далее для всех вариантов keys
      )
      union
      select ... 
      from
    )
    union
    select ... 
    from
  )
  union
  select ... 
  from
)


Re[2]: linq2sql и локальные последовательности
От: Angler Россия  
Дата: 29.12.10 13:14
Оценка:
Здравствуйте, ksg71, Вы писали:

K>Здравствуйте, Angler, Вы писали:


K>как вариант, стройте предикат динамически


Спасибо, это то, что я хотел. Одно только напрягает — ограничение на количество параметров в запросе. Тоесть прийдётся ещё входящую коллекцию keys бить на порции при таком подходе.
Re[3]: linq2sql и локальные последовательности
От: Lloyd Россия  
Дата: 29.12.10 13:18
Оценка:
Здравствуйте, Angler, Вы писали:

L>>По идее должно работать. Правда, не уверен на счет того, насколько эффективно будет в плане перформанса.


A>Генерируется один мега-запросище, но какой


Гы-гы. А если план посмотреть?
Кстати, этот "ужас-ужас" можно упростить до просто "ужаса", если делать union более хитро, разбивая на группы по двое.
Re[3]: linq2sql и локальные последовательности
От: ksg71 Германия  
Дата: 29.12.10 13:20
Оценка:
Здравствуйте, Angler, Вы писали:

A>Здравствуйте, ksg71, Вы писали:


K>>Здравствуйте, Angler, Вы писали:


K>>как вариант, стройте предикат динамически


A>Спасибо, это то, что я хотел. Одно только напрягает — ограничение на количество параметров в запросе. Тоесть прийдётся ещё входящую коллекцию keys бить на порции при таком подходе.


Какое ограничение?
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re[4]: linq2sql и локальные последовательности
От: ksg71 Германия  
Дата: 29.12.10 13:23
Оценка:
Здравствуйте, 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
Re[5]: linq2sql и локальные последовательности
От: Angler Россия  
Дата: 29.12.10 13:34
Оценка:
Здравствуйте, ksg71, Вы писали:

K>1024 параметра в SQL запросе? ну как бы да


ага. у меня помоему при 2048.
Re[4]: linq2sql и локальные последовательности
От: Angler Россия  
Дата: 29.12.10 13:38
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Гы-гы. А если план посмотреть?


а вот кстати план не хуже получился, чем при создании предиката динамически
Автор: ksg71
Дата: 29.12.10


L>Кстати, этот "ужас-ужас" можно упростить до просто "ужаса", если делать union более хитро, разбивая на группы по двое.


тоесть в одном подзапросе возвращать сразу две записи?

t => (t.a1 == key1.a1 && t.a2 == key1.a2 && t.a3 == key1.a2) || (t.a1 == key2.a1 && t.a2 == key2.a2 && t.a3 == key2.a2)
Re[6]: linq2sql и локальные последовательности
От: ksg71 Германия  
Дата: 29.12.10 13:38
Оценка:
Здравствуйте, Angler, Вы писали:

A>Здравствуйте, ksg71, Вы писали:


K>>1024 параметра в SQL запросе? ну как бы да


A>ага. у меня помоему при 2048.


в доке по MS SQL 2008 уже аж 2100 написано, но тут уж ничего не поделаешь
Das Reich der Freiheit beginnt da, wo die Arbeit aufhört. (c) Karl Marx
Re: linq2sql и локальные последовательности
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 29.12.10 13:45
Оценка:
Здравствуйте, Angler, Вы писали:

A>Всем привет,



Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[5]: linq2sql и локальные последовательности
От: Lloyd Россия  
Дата: 29.12.10 13:47
Оценка:
Здравствуйте, Angler, Вы писали:

L>>Гы-гы. А если план посмотреть?


A>а вот кстати план не хуже получился, чем при создании предиката динамически
Автор: ksg71
Дата: 29.12.10


+ еще и строго-типизированно. Чего еще для счастья надо?

L>>Кстати, этот "ужас-ужас" можно упростить до просто "ужаса", если делать union более хитро, разбивая на группы по двое.


A>тоесть в одном подзапросе возвращать сразу две записи?


Нет, имелось в виду, разбивать ключи на две примерно равные группы, по кажной группе строить запрос и union-ить уже эти запросы.
Re[2]: linq2sql и локальные последовательности
От: Lloyd Россия  
Дата: 29.12.10 13:53
Оценка:
Здравствуйте, Sshur, Вы писали:

S>Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?


И что с ней дальше делать? Формировать запрос динамически? Дык это ничуть не легче, чем сформировать динамически нужный expression.
Re[2]: linq2sql и локальные последовательности
От: Lloyd Россия  
Дата: 29.12.10 14:00
Оценка: 4 (1)
Здравствуйте, Sshur, Вы писали:

S>Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?


Кстати, сли развить эту идею, то можно замутить гибридный вариант:
1. Завести в sqlserver-е функцию, принимающую xml и через OPENXML возвращающую табличку с нужной структурой.
2. Добавить эту функцию в datacontext.
3. Использовать функцию в запросе, передавая в кач-ве параметра сериализованную коллекцию ключей.

Нет возможности проверить, но по идее должно работать.
Re[3]: linq2sql и локальные последовательности
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 29.12.10 14:20
Оценка: 4 (1)
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, Sshur, Вы писали:


S>>Я конечно понимаю, что это вообще некошерно и не то, что спрашивал автор, но почему нельзя написать ХП и передать туда строку с идентификаторами через запятую?


L>И что с ней дальше делать? Формировать запрос динамически? Дык это ничуть не легче, чем сформировать динамически нужный expression.


Варианта два, либо разобрать строку, сохранить во временную таблицу и потом сджойнить её с искомой, либо сделать xml и воспользовать OPENXML.

Можно ещё хранимку на .net написать. Это я думаю будет самым быстрым.
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[4]: linq2sql и локальные последовательности
От: Angler Россия  
Дата: 29.12.10 14:55
Оценка:
Здравствуйте, Sshur, Вы писали:

S>Можно ещё хранимку на .net написать. Это я думаю будет самым быстрым.


Если не сложно, откуда начинать копать? )) мелкий примерчик хватил бы с головой. Спасибо.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.