如何筛选可选字段

how to filter for an optional field

我有一个解决方案class:

public class Solution{
   public bool? IsTemplate{get;set;}
   public string createdBy{get;set;}

}

一些文档将 IsTemplate 字段设置为 true 或 false,很多文档没有。

如何获得将其设置为 false 的解决方案以及根本没有该字段的解决方案(遗留文档)?

我尝试通过 IsTemplate 为 null、false、null 或 false 进行过滤,但我从未得到没有 IsTemplate 字段的解决方案。 我必须工作的唯一方法如下,但它丑陋得要命。

 using (IDocumentSession session = DocumentStoreHolder.Store.OpenSession())
            {
                var ret= session.Query<Solution>().Where(x => 
                 x.createdBy.Equals(owner)) //an user's solutions
                .ToList()
                .Where(s => s.IsTemplate == null || s.IsTemplate == false)
                .ToList();
                return ret;
            }

假设第一个 ToList 被使用,因为这个 "document store" 提供的 IQueryable 实现出于某种原因不支持您的查询,您不能做更多。

我建议:

  • 与提供商一起打开错误报告以实现所需的功能,或者如果您有权访问代码库则自行添加。
  • 同时,使用 AsEnumerable 而不是 ToList 以便在继续之前不会缓冲整个数据集。

Where 子句看起来相当简单。如果您的应用程序在 属性 不存在和它为假之间没有语义差异(在您的描述中听起来像它),我会考虑将不存在条件映射到假条件并使用不存在的目标数据结构' 不允许为 nullable IsTemplate.

        using (IDocumentSession session = DocumentStoreHolder.Store.OpenSession())
        {
            return session.Query<Solution>()
                .Where(x => x.createdBy.Equals(owner))
                .AsEnumerable()
                .Select(s => new {
                    IsTemplate = s.IsTemplate ?? false,
                    CreatedBy = s.CreatedBy })
                .ToList();
        }

注意生成的对象是匿名的,我们正在返回它;这使我们无法使用类型良好的方法签名。因此,我肯定会定义另一个Solutionclass。

您可以看到设计自然出现:您现在有两种 Solution 类型。一个用于域,由应用程序使用并且根本不关心遗留条件,如 "IsTemplate" 为空(从应用程序的角度来看它永远不会),另一个仅用于粘合过渡期间的遗留条件。确保对它们进行组织并适当命名,以便清楚它们的用途(利用 .NET 命名空间,这就是它们的长处!)。

您需要创建一个索引来查看缺失的 属性:

from x in docs.Solutions
select new
{
  IsTemplate = x.IsTemplate == true // if this is null, will return false
}

然后查询。

var ret = session.Query<Solution>()
     .Where(x => x.createdBy.Equals(owner)
         && (!x.IsTemplate.HasValue || x.IsTemplate.Value == false))
     .ToList();