【问题标题】:Linq filter by multiple values that may or may not existLinq 按可能存在或不存在的多个值过滤
【发布时间】:2017-06-04 11:06:49
【问题描述】:

我确定以前有人问过这个问题,但我一直没能找到它。 我想根据最终由用户确定的几个标准来过滤表名列表。以下是我当前的代码。

private List<TableMetaData> tableMetaData = new List<TableMetaData>();
public class TableMetaData
{
    public string TableName;
    public string ReferenceTableName;
    public bool IsAuditTable;
    public bool IsSyncTable;
    public bool IsView;
}
public List<string> GetTableNames(TableMetaData filterData)
{
    List<string> filteredNames = tableMetaData
        .Where(table => (table.IsAuditTable == filterData.IsAuditTable)
            && (table.IsSyncTable == filterData.IsSyncTable)
            && (table.IsView == filterData.IsView))
        .Select(table => table.TableName).ToList();

    return filteredNames;
}

我仍然需要在过滤操作中包含 TableMetaData.TableName 和 TableMetaData.ReferenceTableName。但是,这些值可能为空,在这种情况下,它们不会在过滤器中使用。我认为必须有比为每个条件编写单独的 linq 语句更简单的方法?

提前谢谢你。

【问题讨论】:

    标签: c# linq list filter


    【解决方案1】:

    您可以使用单独的 Where 调用,这使其更具可读性(在我看来)

    var nameQuery = tableMetaData
        .Where(table => (table.IsAuditTable == filterData.IsAuditTable)
            && (table.IsSyncTable == filterData.IsSyncTable)
            && (table.IsView == filterData.IsView));
    
    if (filterData.TableName != null)
         nameQuery = nameQuery.Where(table => table.TableName == filterData.TableName);
    
    if (filterData.ReferenceTableName != null)
         nameQuery = nameQuery.Where(table => table.ReferenceTableName == filterData.ReferenceTableName);
    
    // more criteria ..
    
    return  nameQuery.Select(table => table.TableName).ToList();
    

    【讨论】:

    • 这是我的第一次尝试,但它不会编译。 nameQuery 成为 LIst 类型的项目并且不能在第二个过滤器中设置,因为结果是 IEnumerable 类型。很容易解决,但我认为可能有更简单的解决方案。
    • 这当然是正确的答案。 +1 @user1165224 如果你不打电话给ToList()nameQuery 就不可能变成List&lt;T&gt;
    • 我在上面输入并没有收到错误(更正括号)。我第一次一定做了一些有趣的事情。如果我有更多的标准,我宁愿将它们分解以使其比一个长的 linq 语句更具可读性。
    【解决方案2】:

    在使用这些字符串之前,您可以使用string.IsNullOrEmpty 方法来确定这些字符串中的任何一个是null 还是空("")。像这样的:

    public List<string> GetTableNames(TableMetaData filterData)
    {
        List<string> filteredNames = tableMetaData
            .Where(table => (table.IsAuditTable == filterData.IsAuditTable)
                && (table.IsSyncTable == filterData.IsSyncTable)
                && (table.IsView == filterData.IsView)
            && (string.IsNullOrEmpty(filterData.ReferenceTableName) || table.TableName == filterData.TableName)
            && (string.IsNullOrEmpty(filterData.ReferenceTableName) || table.ReferenceTableName == filterData.ReferenceTableName))
            .Select(table => table.TableName).ToList();
    
        return filteredNames;
    }
    

    【讨论】:

      【解决方案3】:

      当然可以。只需在实际条件之前的 or 子句中应用 null 检查。

      例子:

      public List<string> GetTableNames(TableMetaData filterData)
      {
          List<string> filteredNames = tableMetaData
              .Where(table => (table.IsAuditTable == filterData.IsAuditTable)
                  && (table.IsSyncTable == filterData.IsSyncTable)
                  && (table.IsView == filterData.IsView)
                  && ((table.TableName == null) || (table.TableName == "Something"))
                  && ((table.ReferenceTableName == null) || (table.ReferenceTableName == "Something")))
              .Select(table => table.TableName).ToList();
          return filteredNames;
      }
      

      【讨论】:

        【解决方案4】:

        你可以使用 ?操作员可以帮助您解决此问题,如下所示:

        public List<string> GetTableNames(TableMetaData filterData)
        {
            List<string> filteredNames = tableMetaData
                .Where(table => (table.IsAuditTable == filterData.IsAuditTable)
                    && (table.IsSyncTable == filterData.IsSyncTable)
                    && (table.IsView == filterData.IsView)
                    && (filterData.ReferenceTableName == null ? true : table.ReferenceTableName == filterData.ReferenceTableName)
                    && (filterData.TableName == null ? true : table.TableName == filterData.TableName))
                .Select(table => table.TableName).ToList();
        
            return filteredNames;
        }
        

        【讨论】:

        • 这对我很有效。我认为这个解决方案比使用 and 和 or 运算符的混合更具可读性。谢谢。
        • @user1165224 很高兴它有帮助。
        猜你喜欢
        • 2019-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-09
        • 2011-10-03
        • 1970-01-01
        • 2021-02-08
        • 1970-01-01
        相关资源
        最近更新 更多