【问题标题】:Eliminating Redundant NULL checks in Entity消除实体中的冗余 NULL 检查
【发布时间】:2015-02-13 17:12:33
【问题描述】:
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 &amp;&amp; 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 也是单独的表,可能不包含数据。

【问题讨论】:

    标签: c# entity-framework linq-to-entities entity-framework-6


    【解决方案1】:

    通过切换到查询语法并使用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 代码,那么至少这个答案可以做到这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-13
      • 2020-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-04
      相关资源
      最近更新 更多