ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ в системе многие-ко-многим с помощью LINQ Entity Framework

У меня есть отношение «многие ко многим» продуктов (p) и материалов (m) и таблица products2materials (p2m) как ссылка «многие ко многим».

мне нужно получить

- all products that have materials assigned,
- all products with no materials assigned,
- and all materials with no products assigned.

В основном это союз того, что есть. Однако, поскольку это будет фильтр данных, мне нужно отфильтровать продукты и / или материалы, которые не соответствуют критериям поиска (например, все продукты, начинающиеся с "A" и т. Д.).

Как это сделать в LINQ-to-EF 4.1?

Большое спасибо!


person John    schedule 24.01.2012    source источник
comment
На данный момент, и поскольку полные внешние соединения в LINQ кажутся головной болью, я думаю о представлении, в котором я буду запускать запрос LINQ. В представлении уже будут необходимые JOINS, и выполнение запросов LINQ станет намного проще.   -  person John    schedule 25.01.2012


Ответы (3)


Следующее должно работать:

from m in context.Materials //m has to be the first
from p in context.Products    
where !p.Select(p1 => p1.Material).Contains(m) || p.Material == null || p.Material == m

Для производительности, наверное, лучше было бы следующее:

var a = from p in context.Products select p.Material;

var b = from m in context.Materials //m has to be the first
        from p in context.Products    
        where a.Contains(m) || p.Material == null || p.Material == m 
person yoel halb    schedule 11.11.2013

Linq не предлагает операции полного внешнего соединения напрямую, поэтому лучше всего попробовать отдельные запросы L2E с левым и правым соединением и объединить их в единый набор результатов.

Я бы попробовал что-то вроде (не проверено):

var query = (from p in context.Products
             from m in p.Materials
             select new { p, m })
            .Union(
             from m in context.Materials
             from p in m.Products
             select new { p, m })
            ...

Возможно, вам придется использовать DefaultIfEmpty для принудительного выполнения внешних соединений.

person Ladislav Mrnka    schedule 24.01.2012

Из вашего описания похоже, что вам действительно нужны:

  1. Все продукты
  2. Все неиспользованные материалы

Вам нужен его как один IQueryable (если да, какие поля вам нужны) или как два IQueryable?

person Vitaliy Kalinin    schedule 24.01.2012
comment
Ну, мне действительно нужны все продукты, да, но также и все материалы, в зависимости от того, что хочет пользователь. Пользователь может выбрать, нужен ли ему конкретно материал, связанный с продуктом, или материал, который еще не связан. - person John; 25.01.2012