Linq to SQL: порядок по значению в связанной таблице - PullRequest
4 голосов
/ 03 января 2009

У меня есть 2 таблицы, которые в упрощенном виде выглядят так:

Products(
   id: int,
   name: varchar
);

ProductSpecs(
   product_id: int,
   spec_name: varchar,
   spec_value: int
);

Теперь мне нужно отсортировать товары (от linq до sql) по значению какого-то элемента спецификации (например, «цена») Поэтому я делаю что-то вроде этого

var products = from p in db.Products
               from ps in p.ProductsSpecs
               where ps.spec_name == "price"
               orderby ps.spec_value
               select p;

Проблема заключается в том, что если такой ProductSpec с именем-спецификацией "price" нет, продукт вообще не включается. Я могу добавить эти продукты с помощью Union или Concat, но сортировка первой части не будет сохранена.

Как лучше всего с этим справиться?

Спасибо.

Ответы [ 3 ]

8 голосов
/ 03 января 2009

Во-первых, я бы порекомендовал вам сделать это на чистом SQL как функцию или хранимую процедуру, а затем получить к нему доступ через linq или добавить столбец цен в таблицу продуктов. Кажется, что цена будет нормальным атрибутом, добавляемым ко всем вашим продуктам, даже если эта цена равна NULL.

SQL:

select p.*
from products p
left outer join productspecs ps on
    p.id = ps.product_id
    and ps.spec_name = 'Price'
order by ps.spec_value

С учетом вышесказанного, вот странный бит LINQ, который должен работать на вашей таблице (возможно, некоторые имена столбцов написаны неправильно):

var products = from p in db.Products
               join ps in (from pss in db.ProductSpecs
                           where pss.spec_name== "Price"
                           select pss
                           ) on p.id equals ps.product_id into temp
               from t in temp.DefaultIfEmpty()
               orderby t.spec_value
               select p;

Я проверил это на некоторых настройках таблиц, как описано выше, и создал 5 продуктов, три с ценами в разных порядках значений, и этот LINQ упорядочил их так же, как и в приведенном выше SQL, и также возвратил нулевые строки результата.

Надеюсь, это работает!

0 голосов
/ 03 января 2009

Разве вы не можете просто присоединиться?

var products = из п в дб. объединить ps в db.ProductSpecs для p.id равно ps.product_id где ps.spec_name == "цена" orderby ps.spec_value выберите p;

0 голосов
/ 03 января 2009

В обычном SQL вы бы использовали LEFT OUTER JOIN. Это сохраняет строки, которые появляются в левой таблице (та, что указана первой), даже если в правой таблице нет совпадающей строки (вторая в списке и та, которая является внешним соединенным). Вы получите пустые значения для значений, которые должны быть, но не присутствуют в правой таблице. Таким образом, цена для тех товаров, у которых отсутствует цена, будет выглядеть как NULL.

То, к чему это приводит в LINQ to SQL, - другое дело.

Вы можете подумать о том, разумно ли иметь продукты, у которых нет цены. Вы эмулируете что-то, называемое EAV - таблицы сущностей, атрибутов, значений - и они обычно рассматриваются как «нехорошая вещь».

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