2013-11-21 3 views
2

У меня есть запрос ссылки с простым соединением к нескольким таблицам и предложением where, по какой-то нечетной причине запрос, похоже, не подчиняется предложению where.Запрос LINQ - соединение и где условие не соблюдается?

Мой запрос, как показано ниже:

from p in Platforms 
join c in Compartments on p.Id equals c.PlatformId 
join ci in CompartmentItems on c.Id equals ci.CompartmentId  
where p.Id == 4042 && !ci.Archived && !c.Archived 
select c 

И простой LINQPad screnshot показывает, что CompartmentItems возвращаются прикреплены к Compartments, но независимо от того, являются ли они архивируются или нет.

enter image description here

Он чувствует, как я быть плотными здесь, кто может мне помочь определить проблему с запросом?

Любые мысли очень ценятся.

EDIT: Итак, я вернулся и более подробно рассмотрел это и установил, почему я только вернул отсеки. Это связано с репозиторием, который только типично возвращает типы доменов для потребления. В результате я не могу вернуть более одного типа сущности без введения одного случайного объекта типа DTO (ни один из других репозиториев не возвращает ничего, кроме доменных типов).

Так с этим в виду, у меня есть 4 варианта:

  1. Создать случайный DTO только для этой одной цели
  2. запросов БД дважды и получить детали отсека в качестве второго запроса
  3. возвращающих IQueryable из репозитория (опять же, это не делается нигде)
  4. Возвращайте отсеки независимо от архивных отсеков и отфильтровывайте их в режиме потребления в памяти.

Любые мысли о наилучшем подходе здесь?

+2

Ваша последняя строка 'выбрать c'. Так вот что делает запрос. – JeremiahDotNet

ответ

5

Вы берете свое отделение, присоединяетесь к нему с элементами отделения, отфильтровываете некоторые предметы отделения, затем , игнорируя все предметы отделения, вы присоединились к столу, полностью выбрав только отсеки, а затем используя совершенно другой механизм, чтобы получить все предметы отсека для каждого отсека, а именно использование встроенного свойства отношения.

Чтобы получить только элементы, соответствующие Ваш отсечные данный фильтр, что вам нужно на самом деле выбрать из пунктов отсека вы фильтруетесь с помощью пункта select, а затем не использовать Include, чтобы включить их все. Это может выглядеть примерно так:

from p in Platforms 
join c in Compartments on p.Id equals c.PlatformId 
join ci in CompartmentItems.Where(ci => !ci.Archived) 
on c.Id equals ci.CompartmentId into compItems  
where p.Id == 4042 && !c.Archived 
select new 
{ 
    Compartment = c, 
    CompartmentItems = compItems, 
} 
+0

Спасибо за объяснение, знал, что я был глупым. Когда я подумаю об этом в SQL, концепция выбора значений из основной таблицы потребует второго запроса для получения дочерних элементов, что, конечно же, не будет использовать одно и то же условие. #facepalm – dougajmcdonald

1

Посмотрите на сам SQL-запрос. Я уверен, что он подчиняется вашим фильтрам. Готов поспорить, что у вас есть ленивая загрузка, поэтому вы видите все CompartmentItems.

Или, если вы не используете SQL-сервер, у вас должна быть связь между отсеком и CompartmentItems. Когда вы используете свойство навигации, он вернет все куки.

Здесь нет ошибок.

Попробуйте создать отсек со всеми CompartmentItems.Archived = 1. Вы увидите, что это отделение не будет возвращено вашим заявлением.

0

Попробуйте сделать это вот так.

from p in Platforms 
join c in Compartments on p.Id equals c.PlatformId 
join ci in CompartmentItems on c.Id equals ci.CompartmentId  
where p.Id == 4042 
where !ci.Archived 
where !c.Archived 
select c 

Возникает проблема связи, пытающейся запросить одну и ту же запись для объекта. Когда логика отделена & & кажется, что читается на машине, как

p.Id == 4042 && !p.Archived && !p.Archived 

Что является результатом LINQ применения фильтров с использованием только первый элемент в списке, независимо от разности оставшихся Предметы.

0

Linq Соединение с в п и где условие

var li = (from cert in db.tbl_ISOCetificate 
      join comCert in db.tbl_ComGroupCertificate.Where(x=>x.GroupID ==GroupID) on cert.Cert_id equals comCert.CerID into jo 
      from b in jo.DefaultIfEmpty() 
      select new { cert.Cert_id, cert.Cert_Name}).ToList(); 
Смежные вопросы