检查value是否为null,如果是,则执行extra(sub)查询

时间:2013-10-01 07:50:25

标签: c# linq entity-framework

是否可以在LINQ查询中检查空值,当值为null时,它是否一次执行额外(子)查询?

解释

我在我的数据库中声明了默认按钮,默认描述。用户可以自定义这些按钮,这些设置存储在ButtonLocations表中。现在,每个按钮都有标准描述,用户可以编辑此描述。当用户编辑描述时,它将存储在我的数据库中的Descriptions表中。 当我检索所有按钮时,我首先检查按钮是否具有特定描述(在 buttonlocations 中,左连接)。如果不是这样(因此为null),我将检索默认描述。

目前,我获取了所有实体的描述,然后我遍历所有实体以检查值是否为空。这导致对数据库的多次查询。

var temp = (from bl in context.buttonLocations
                    join b in context.Buttons
                    on bl.ButtonID equals b.ButtonID into buttons
                    from button in buttons.DefaultIfEmpty()
                    join d in context.Descriptions
                    on new
                    {
                        ID = bl.ButtonLocationID,
                        langID = languageID,
                        originID = descriptionOriginID
                    }
                    equals new
                    {
                        ID = d.ValueID,
                        langID = d.LanguageID,
                        originID = d.DescriptionOriginID
                    }
                    into other
                    where bl.ButtonGroupID == buttonGroupId
                    from x in other.DefaultIfEmpty()
                    select new
                    {
                        Button = button,
                        ButtonLocation = bl,
                        Description = x
                    }).ToList();

        // Retrieve default descriptions if no specific one is set
        foreach (var item in temp)
        {
            if (item.Description == null)
            {
                item.Description = context.Descriptions
                    .FirstOrDefault(x => x.ValueID == item.Button.ButtonID && x.LanguageID == languageID && x.DescriptionOriginID == (short)DescriptionOriginEnum.Button);
            }
        }

2 个答案:

答案 0 :(得分:0)

null coalescing operator应该适合你。像这样:

.....
select new
{
   Button = button,
   ButtonLocation = bl,
   Description ?? context.Descriptions
                         .FirstOrDefault(
                         x => x.ValueID == button.ButtonID 
                         && x.LanguageID == languageID 
                         && x.DescriptionOriginID == (short)DescriptionOriginEnum.Button)
})

答案 1 :(得分:0)

我认为Colin使用coalesce运算符的答案应该有效,但如果无法使用,可以尝试做一个获得两个选项的子选择,然后按优先顺序排序自定义源,并获取最高记录。 (我在这里假设任何给定的按钮只有一个描述,多个描述不应该导致多个按钮。)

var temp = (from bl in context.buttonLocations
        join b in context.Buttons
        on bl.ButtonID equals b.ButtonID into buttons
        from button in buttons.DefaultIfEmpty()
        let description = (
                from d in context.Descriptions
                where
                    d.LanguageID == languageID
                 && (
                      (
                        d.ValueID == bl.ButtonLocationID
                        && d.DescriptionOriginID == descriptionOriginID
                      )
                    ||
                      (
                        d.ValueID == b.ButtonID 
                        d.DescriptionOriginID == (short)DescriptionOriginEnum.Button
                      )
                    )
                // this line puts custom descriptions first
                orderby d.DescriptionOriginID == (short)DescriptionOriginEnum.Button
                        ? 1
                        : 0
                select d
                )
                // this will get a custom description if there was one, otherwise
                // the first one will be the default description
                .FirstOrDefault() 
        where bl.ButtonGroupID == buttonGroupId
        select new
        {
          Button = button,
          ButtonLocation = bl,
          Description = description
        })
        .ToList();

这显然有点尴尬,可能不是最有效的查询。我会尝试首先将合并运算符移动到let description = d ?? /*subselect*/行。