我正在尝试创建一个LINQ to SQL查询,我真的很难过。
我有一个包含多个表的数据库,可以创建一个成功返回单个连接结果的查询。我遇到的问题是引入第二次加入。
SQL语句很容易生成
USE InlandMarina
SELECT *
FROM Slip s LEFT JOIN Lease l ON s.id = l.slipid
WHERE GETDATE() > l.EndDate OR ISNULL(l.startdate, '') = ''
我已经生成了两个函数LINQ查询,这些查询单独返回所需的结果,但不能成功地将两者结合。
var nulledSlips = from slips in theContext.Slips
join nulled in theContext.Leases on slips.ID equals nulled.SlipID into slipsNulled
from nulledEndDate in slipsNulled.Where(nulled => nulled.EndDate==null).DefaultIfEmpty()
返回所有在数据库中没有设置结束日期的单据(null),它们从未被租用过。
from expiredSlips in theContext.Slips
join leased in theContext.Leases on slips.ID equals leased.SlipID into allSlips
from leased in allSlips
where leased.EndDate < DateTime.Today
返回租约已到期的单据。
我希望能够做的是将两个查询以某种方式组合成一个返回所有从未出租或租约到期的单据。
任何帮助都会非常感激,我已经在这里待了两天,再也看不到树林了。
架构是四个表;租赁,滑动,码头,位置。 租 PK ID FK SlipID
滑 PK ID FK DockID
基座 PK ID FK LocationID
地点 PK ID
修改后的查询是:
var expiredSlips = from slips in theContext.Slips
join nulled in theContext.Leases on slips.ID equals nulled.SlipID into slipsNulled
from nulledEndDate in slipsNulled.Where(nulled => nulled.EndDate == null).DefaultIfEmpty()
join leased in theContext.Leases on slips.ID equals leased.SlipID into allSlips
from leased in allSlips.Where(leased=> leased.EndDate < DateTime.Today).DefaultIfEmpty()
返回:
<SlipsDTO>
<SlipID>1000</SlipID>
<Width>8</Width>
<Length>16</Length>
<DockID>1</DockID>
<WaterService>true</WaterService>
<ElectricalService>true</ElectricalService>
<MarinaLocation>Inland Lake</MarinaLocation>
<LeaseStartDate xsi:nil="true" />
<LeaseEndDate xsi:nil="true" />
</SlipsDTO>
产生一切。如果我删除最后一个.DefaultIfEmpty(),我得到的结果集只有已经有租约的单据;当前或已过期。
答案 0 :(得分:1)
如果FK已经到位,通常你不必自己使用linq-to-sql进行“连接”步骤,你可以只引用导航属性。另外,请记住,您可以使用“let”在查询中定义可能使您更容易进行查询的内容。
由于FK是通过具有SlipID的租赁方式,因此看起来给定的单据可以与其关联的任何数量(0 ... *)的租约,尽管您的逻辑似乎表明它只是0或1 - 如果这是真的,滑动上可以为空的FK LeaseID可能更有意义,但这是一个切线。现在我将坚持原来的SQL逻辑,即“任何相关的租约已过期”
var query =
from slip in context.Slips
let expiredLeases = slip.Leases.Where(lease => lease.EndDate < DateTime.Today)
where slip.Leases.Any() == false // no leases for this slip yet
|| expiredLeases.Any() // at least one associated lease is expired
select slip;
当然,您仍然可以构建一个没有导航属性的查询,但我发现使用生成的导航属性而不是手动指定连接及其条件更容易且更不容易出错:)