List<OfferDTO> offers = dbContext.Offer.Where(x => x.IsDeleted)
.OrderBy(i => i.OfferID)
.Skip(start).Take((length))
.Select(y => new OfferDTO
{
OfferStageValue = y.OfferStage.Value ?? null,
PropertyAddressLine1 = (y.PropertyAuction.Property != null && y.PropertyAuction.Property.Address != null) ? y.PropertyAuction.Property.Address.AddressLine1 : string.Empty,
PropertyAddressLine2 = (y.PropertyAuction.Property != null && y.PropertyAuction.Property.Address != null) ? y.PropertyAuction.Property.Address.AddressLine2 : string.Empty,
PropertyCity = (y.PropertyAuction.Property != null && y.PropertyAuction.Property.Address != null) ? y.PropertyAuction.Property.Address.City : string.Empty,
PropertyZip = (y.PropertyAuction.Property != null && y.PropertyAuction.Property.Address != null) ? y.PropertyAuction.Property.Address.PostalCode : string.Empty,
})
.ToList();
在上面的例子中,我使用select语句直接转换为对象。
在新对象中使用它们的值之前,需要检查某些属性的null
值。
但是,如您所见,不同的属性会一遍又一遍地检查null
的相同值。具体来说,你看:
(y.PropertyAuction.Property != null && y.PropertyAuction.Property.Address != null)
连续几次检查。
在随后的SQL中,您看到查询每次都在检查null
:
CASE WHEN (([Extent12].[PropertyID] IS NOT NULL) AND ([Extent13].[AddressID] IS NOT NULL)) THEN [Extent14].[AddressLine1] ELSE @p__linq__1 END AS [C5],
CASE WHEN (([Extent12].[PropertyID] IS NOT NULL) AND ([Extent15].[AddressID] IS NOT NULL)) THEN [Extent16].[AddressLine2] ELSE @p__linq__2 END AS [C6],
CASE WHEN (([Extent12].[PropertyID] IS NOT NULL) AND ([Extent17].[AddressID] IS NOT NULL)) THEN [Extent18].[City] ELSE @p__linq__3 END AS [C7]
有没有办法检查一次并将其结束,或者这是安全使用这些值的最佳方法吗?
注意
y
是基表
PropertyAuction
,
Property
,和
Address
也是所有单独的表,可能不包含数据。
答案 0 :(得分:1)
通过切换到Query语法并使用let
关键字,您可以在LINQ本身中获得更多优雅,但我认为您将发现您生成的SQL(必须)非常相似:
var offers = (from o in dbContext.Offers
where o.IsDeleted
let p = o.PropertyAuction.Property
let a = p != null ? p.Address : null
orderby o.OfferID
select new OfferDTO
{
OfferStageValue = o.OfferStage.Value,
PropertyAddressLine1 = a != null ? a.AddressLine1 : string.Empty,
PropertyAddressLine2 = a != null ? a.AddressLine2 : string.Empty,
PropertyCity = a != null ? a.City : string.Empty,
PropertyZip = a != null ? a.PostalCode : string.Empty,
})
.Skip(start).Take(length)
.ToList();
修改强>
刚才有机会将完整模型放入编译器并检查SQL - 正如预期的那样,生成的SQL与从原始查询生成的SQL相同; (即,即使提取到LINQ中的单个检查中,生成的SQL也会将这些检查内联四次,从而生成相同的SQL代码)。
如果您的主要目标是更清晰的LINQ代码,那么至少这个答案可以实现。