简体   繁体   English

LINQ查询-加入和不遵守where子句?

[英]LINQ query - join and where clause not being obeyed?

I have a link query with a simple join to a couple of tables, and a where clause, for some odd reason the query doesn't seem to be obeying the where clause. 我有一个链接查询,其中有一个简单的联接到几个表和一个where子句,出于某些奇怪的原因,该查询似乎并没有遵循where子句。

My query is as below: 我的查询如下:

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

And a simple linqpad screnshot shows that the CompartmentItems are returned attached to the Compartments but irrespective of whether they are archived or not. 一个简单的linqpad screnshot显示,将CompartmentItems附加到了Compartments ,而不管它们是否已归档。

在此处输入图片说明

It feels like I'm being dense here, can anyone help me identify the issue with the query? 感觉我在这里很忙,有人可以帮助我确定查询的问题吗?

Any thoughts greatly appreciated. 任何想法表示赞赏。

EDIT: So I went back and looked at this in more detail and established why I had only returned the compartments. 编辑:所以我回过头来,更详细地研究了这个问题,并确定了为什么我只退回了车厢。 It's due to a repository which only typically returns domain types for consumption. 这是由于存储库通常仅返回域类型以供使用。 As a result, I can't return more than one entity type without introducing a single random DTO type object (none of the other repos return anything other than domain types). 结果,在不引入单个随机DTO类型对象的情况下,我不能返回多个实体类型(其他存储库都没有返回域类型以外的任何东西)。

So with this in mind I have 4 options: 因此,考虑到这一点,我有4个选择:

  1. Create a random DTO just for this one purpose 为此目的创建一个随机的DTO
  2. Query the db twice and get the compartment items as a second query 查询数据库两次,并获取隔离专区项作为第二个查询
  3. Return an IQueryable from the repository (again, this is not done anywhere else) 从存储库返回一个IQueryable(同样,在其他任何地方都不会执行此操作)
  4. Return the compartments irrespective of archived compartmentitems and filter them out in the consuming method in memory. 不管已归档的隔离专区,都返回隔离专区,并使用内存中的使用方法将其过滤掉。

Any thoughts on the best approach here? 对最佳方法有何想法?

You're taking your compartment, joining it with the compartment items, filtering out some compartment items, then ignoring all of the compartment items you joined the table with entirely by only selecting out the compartments, and then using an entirely different mechanism to get all compartment items for each compartment, namely using the built in relationship property. 您要带走隔间,将其与隔间项目连接在一起,过滤掉一些隔间项目,然后仅选择隔间,然后完全 忽略所有加入表的隔间项目 ,然后使用完全不同的机制来获取所有隔间每个隔离专区的隔离专区项目,即使用内置的关系属性。

To get only the compartment items matching your given filter you need to actually select out the compartment items you filtered using your select clause, and then not use Include to include them all. 要仅获取与给定过滤器匹配的隔离专区项目,您实际上需要选择出使用select子句过滤的隔离专区项目,然后使用Include将其全部Include在内。 This might look something like: 这可能看起来像:

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,
}

Look at the SQL query itself. 查看SQL查询本身。 I'm sure it obeys your filters. 我确定它会遵守您的过滤条件。 I bet you have lazy loading on, that's why you're seeing all the CompartmentItems. 我敢打赌,您会延迟加载,这就是为什么您看到所有CompartmentItems的原因。

Or if your not using SQL backend, you must have a relationship between Compartment and CompartmentItems. 或者,如果您不使用SQL后端,则必须在Compartment和CompartmentItems之间建立关系。 When you use the navigation property it'll return all the compartmentitems. 当您使用导航属性时,它将返回所有隔离专区。

There is no bug here. 这里没有错误。

Try create a Compartment with all CompartmentItems.Archived = 1. You'll see this compartment is not going to be returned by your statement. 尝试使用所有CompartmentItems.Archived = 1创建一个隔间。您将看到此语句不会返回该隔间。

Try doing it like this. 尝试这样做。

    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

It gets you around the issue of link trying to query the same record for the property. 它可以解决链接尝试查询属性的相同记录的问题。 When the logic is separated by && it seems like it is read to the machine as 当逻辑由&&分隔时,似乎将其读入机器

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

Which is the result of LINQ applying the property filters using only the first item in the list regardless of the difference of the remaining items. 这是LINQ仅使用列表中的第一项应用属性过滤器的结果,而与其余项的差异无关。

Linq Join with into clause and where condition Linq用into子句和where条件连接

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM