【问题标题】:Filter by a class that has null properties按具有空属性的类过滤
【发布时间】:2021-10-29 07:10:17
【问题描述】:

我的存储库中有一个获取列表的方法,该方法有一个这样的类:

Public Class FilterDTO{
    public string City { get; set; }
    public string Country { get; set; }
    public DateTime InitDate { get; set; }
    public DateTime EndDate { get; set; }
    public Guid UserId { get; set; }
}

进行查询,但并非总是所有属性都有值,如果我想按日期过滤,我发送 DateTime 属性的值,但如果我想按 City 过滤,我只发送 City 属性,所以有时一些属性为空并且查询不返回任何内容,这是我在存储库中的方法:

public async Task<List<ListUser>> getListUserByFilter(FilterDTO filter)
{
    var listUsers = await _context.ListUser.Where(lu => lu.UserId == filter.UserId
                    && lu.City == filter.City
                    && lu.Country == filter.Country
    ).ToListAsync();
    return listUsers;
}

在我的数据库中,有 9 个带有此 City、Country 和 UserId 的寄存器,但查询没有返回任何内容,因为我认为其他属性为 null,所以我的问题是如何进行查询以返回这 9 个寄存器。

【问题讨论】:

  • 您是否尝试过包括城市、国家/地区等?
  • 请注意DateTime 不能为空。你需要DateTime?
  • 你可以拆分表达式,所以你有一个IQuerable。然后你可以做类似if( !string.IsNullOrEmpty(filter.City)) { query = query.Where( lu =&gt; lu.City == filter.City ); } ...
  • @Fildor 我只需要输入“?”在 DateTime 之后?,但如果我想按日期获取其他属性将为 null,所以查询将起作用?
  • 不,不是这样。照原样,如果您执行 new FilterDTO() ,它将其 DateTime 属性设置为 default(DateTime)not null。所以,如果你用这些查询,你最终会得到一个像 " WHERE Start >= X AND End DateTime?来区分“无价值”,所以可以省略where子句的那部分。

标签: c# linq entity-framework-core .net-5


【解决方案1】:

您可以在检查每条记录是否与特定过滤器匹配之前添加一个子句来检查过滤器字段是否为空。

不过,对于 DateTime 字段,您需要通过将类型从 DateTime 更改为 DateTime 来使它们可以为空,如下所示:

public class FilterDTO{
    public string City { get; set; }
    public string Country { get; set; }
    public DateTime? InitDate { get; set; }
    public DateTime? EndDate { get; set; }
    public Guid UserId { get; set; }
}

然后,对于 null 检查,您可以执行以下操作:

public async Task<List<ListUser>> getListUserByFilter(FilterDTO filter)
{
    var listUsers = await _context.ListUser
        .Where(lu => !filter.InitDate.HasValue || lu.CreationDate >= filter.InitDate.Value)
        .Where(lu => !filter.EndDate.HasValue || lu.CreationDate <= filter.EndDate.Value)
        .Where(lu => filter.UserId is null || lu.UserId == filter.UserId)
        .Where(lu => filter.City is null || lu.City == filter.City)
        .Where(lu => filter.Country is null || lu.Country == filter.Country)
        .ToListAsync();
    return listUsers;
}

null 检查必须在相等检查之前,并且在它们之间使用 OR (||) 可确保在 null 情况下第二个条件(实际过滤器)将被忽略。

附:将多个 .Where(...) 调用链接在一起使得它们在最终查询中表现为 AND (&&),并且,以我的拙见,使阅读它的眼睛更容易:)

【讨论】:

  • 请注意,要使其正常工作,您需要从 DateTime 转到 DateTime?DateTime 属性不能null
  • @Fildor 你完全正确。谢谢你。我已经更新了答案以使其正确:)
  • @GabrielCascaes 它对我不起作用:(
  • @AndresGuillenHernandez 你介意分享更多关于你如何测试它和你得到的结果的细节吗?有什么错误吗?也许用更新的代码和更新的结果更新问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
  • 2018-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 2020-08-03
相关资源
最近更新 更多