可空 bool 列的 LINQ Where 子句中的三元运算符

Ternary Operator in LINQ Where clause for nullable bool column

任何人都可以看到这个 linq 语句中的三元组有什么问题吗:

var organizations = Context.Set<Domain.Content.Organisation>()
                    .Where(x => x.ShowCompanyPage == (showCompanyPagesOnly ? true : x.ShowCompanyPage))

如果 showCompanyPagesOnly 设置为 true,我得到 4 个结果,这是正确的,只有四个公司有 ShowCompanyPage = true。

但是,如果我将其设置为 false,我预计会有 1000 多个结果(所有公司)。但我仍然只得到 4.

我的逻辑是不是:

if showCompanyPagesOnly is true, then give me results where  x.ShowCompanyPage == true

else give me results where  x.ShowCompanyPage = whatever is in the column (ie ALL Organisations)

?

x.ShowCompanyPage 是一个可为空的 bool 列。

完整代码:

public Result<IList<Organisation>> GetAllOrganisations(bool showCompanyPagesOnly = false)
    {
        var result = new Result<IList<Organisation>>();

        try
        {
            var organizations = Context.Set<Domain.Content.Organisation>()
                .Where(x => x.ShowCompanyPage == (showCompanyPagesOnly == true ? true : x.ShowCompanyPage)) // show only company pages or show all
                .AsNoTracking()
                .Select(x => new DataContracts.Content.Organisation
                {
                    Id = x.Id,
                    Name = x.Name,
                    OrganisationTypeId = x.OrganisationTypeId,
                    IsCustomer = x.IsCustomer,
                    SeoName = x.SeoName,
                    Description = x.Description,
                    Website = x.Website
                }).OrderBy(x => x.Name).ToList();

            result.Data = organizations;
        }
        catch (Exception ex)
        {
            result.SetException(ex);
            HandleError(ex);
        }
        return result;

    }

试试这个:

.Where(x => showCompanyPagesOnly ? x.ShowCompanyPage == true : true)

这里是fiddle.

Where() 函数 returns 记录满足条件,因此条件必须计算为布尔值(即 truefalse)。如果您将值 true 放入条件中,那么您实际上是在请求 Where() 函数 return 所有记录。它类似于:

if(true){
    //do something.
}

如您所知,这将始终执行 "do something"。

有时当逻辑变得太复杂时,最好的答案就是把问题颠倒过来,目前你在问

如果 showCompanyPagesOnly 为真,我如何只获得带有 ShowCompanyPage = true 的那些

如果您将其与 get everything 交换,除非 showCompanyPagesOnly 为 true 并且您的逻辑变为简单的 OR 语句

showCompanyPagesOnly 不正确或 ShowCompanyPage 正确 这是

x => (!showCompanyPagesOnly) || x.ShowCompanyPage

您可能需要这样做

   x => (!showCompanyPagesOnly) || (x.ShowCompanyPage ?? false)/*default value depends on if you want to treat null as true or false*/)

考虑可空性

这是一种更好的方法,因为它将生成两个不同的 LINQ 查询,这将允许 SQL 服务器生成两个不同的查询计划,这在大多数情况下会极大地影响查询的性能:

public Result<IList<Organisation>> GetAllOrganisations(bool showCompanyPagesOnly = false)
{
    var result = new Result<IList<Organisation>>();

    try
    {
        var organizations = Context.Set<Domain.Content.Organisation>()
            .AsNoTracking();

        if (showCompanyPagesOnly)
            organizations=organization
            .Where(x => x.ShowCompanyPage == true);

        result.Data = organizations
            .Select(x => new DataContracts.Content.Organisation
            {
                Id = x.Id,
                Name = x.Name,
                OrganisationTypeId = x.OrganisationTypeId,
                IsCustomer = x.IsCustomer,
                SeoName = x.SeoName,
                Description = x.Description,
                Website = x.Website
            }).OrderBy(x => x.Name).ToList();
    }
    catch (Exception ex)
    {
        result.SetException(ex);
        HandleError(ex);
    }
    return result;

}