LINQ查询 - join和where子句没有被遵守?

时间:2013-11-21 17:47:49

标签: c# linq where-clause

我有一个简单连接到几个表的链接查询,以及一个where子句,由于某些奇怪的原因,查询似乎没有遵守where子句。

我的查询如下:

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

感觉我在这里很密集,任何人都可以帮我识别查询问题吗?

任何想法都非常感激。

编辑: 所以我回过头来仔细研究了这一点,并确定了为什么我只退回隔间。这是由于存储库通常只返回要消费的域类型。 因此,在不引入单个随机DTO类型对象的情况下,我不能返回多个实体类型(其他repos都不会返回除域类型之外的任何内容)。

因此,我有4个选择:

  1. 仅为此目的创建随机DTO
  2. 查询数据库两次并将隔离专区项目作为第二个查询
  3. 从存储库返回IQueryable(再次,这在其他任何地方都没有)
  4. 返回隔间,不论存档的隔离专区是什么,并在内存中的消耗方法中将其过滤掉。
  5. 有关最佳方法的任何想法吗?

4 个答案:

答案 0 :(得分: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,
}

答案 1 :(得分:1)

查看SQL查询本身。我确信它服从你的过滤器。我打赌你有懒加载,这就是你看到所有CompartmentItems的原因。

或者,如果您不使用SQL后端,则必须在Compartment和CompartmentItems之间建立关系。当您使用导航属性时,它将返回所有隔离专区。

这里没有错误。

尝试使用所有CompartmentItems.Archived = 1创建一个隔间。您将看到您的声明不会返回此隔间。

答案 2 :(得分: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仅使用列表中的第一项应用属性过滤器的结果,而不管剩余项目的差异。

答案 3 :(得分:0)

Linq加入into子句和where condition

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();