【问题标题】:Linq Contains to return ALL items or selected ones?Linq 包含返回所有项目或选定的项目?
【发布时间】:2011-09-04 10:49:51
【问题描述】:

是否可以编写一个带有 where 子句的 linq select,它可以选择所有项目或特定项目?在 SQL 中,我可以使用 "where currency like '%'" 来返回所有内容。 我正在尝试编写一种方法,以便我可以传入货币(以及其他一些东西)并重复使用相同的方法。

例如

只要英镑

from a in accounts
where currency.Contains('GBP')
select a

只要英镑

from a in accounts
where currency == 'GBP'
select a

所有货币?

from a in accounts
where currency like '%'
select a

【问题讨论】:

  • 哪个 LINQ 提供程序?这是基于表达式还是委托?
  • 如果你想要全部,那么只需删除表达式所在的孔
  • 或“其中货币 == 货币”;) 我看不出问题
  • 如何从语句中删除 where 子句?我想尝试一个可以调用的方法来返回 ALL 或特定的?

标签: c# linq


【解决方案1】:

您是否尝试过“存储”查询并在后续步骤中对其进行过滤,如下所示:

IEnumerable<AccountClass> GetAccounts(string filter = null)
{
    var query = from a in accounts select a;
    if (!string.IsNullOrEmpty(filter))
    {
        query = query.Where(a => a.Currency.Contains(filter));
    }
    return query;
}

这可以在单个查询中折叠,但对我来说似乎不太可读,并且可能不适用于 LINQ-to-SQL(或表达式被转换为的其他 LINQ-to-DB查询):

from a in accounts
where string.IsNullOrEmpty(filter) || a.Currency.Contains(filter)
select a

【讨论】:

  • IEnumerable -> IEnumerable
【解决方案2】:

你可以试试

.Where(c => currencyToFind == null ? true : c==currencyToFind)

如果您想要所有货币,请为您想要的货币传入一个空值。

在 linq 查询表达式中:

from a in accounts
where (currencyToFind == null ? true : account.Currency==currencyToFind)
select a

【讨论】:

  • 你能在 linq "from...where...select" 以及 IEnumerable.Where() 中执行此操作吗?
  • 当然,您只需要将条件放在 where 子句中。我将编辑我的答案以添加它。另外,我相信您所说的链接类型的名称是“Linq 表达式”。披露:我没有坐在编译器附近,我无法检查它是否有效,但我相信它确实有效。
  • 谢谢 - 这是我想要的最佳答案:用户可以选择货币代码或不选择货币代码,然后两次取回结果集。
  • 我想纠正自己,@BlueChippy 所说的这种 linq 类型不称为 linq 表达式,而是称为“Linq 查询语法”,有时也称为“Linq 查询表达式”。另一种类型(我首先提到的是扩展方法,称为“Linq 方法语法”。所以我不会混淆以后来这里的任何人!
【解决方案3】:

如果您想返回所有货币,请不要使用任何where(在 LINQ 和 SQL 中):

from a in accounts
select a

或者,如果您真的不需要做任何其他事情,只需使用accounts

编辑:如果您想要一种方法,例如,任何货币都由null 表示,您可以这样做:

IQueryable<Account> result = accounts;

if (currency != null)
    result = result.Where(a => a.Currency == currency);

return result;

【讨论】:

  • 这可行,但意味着我有两种方法 - 一种用于特定货币,一种用于所有货币
  • 这是迄今为止最有希望和最明智的......因为我需要我的方法做的是返回一个不同的具体类(非 EF)的列表,避免“无参数构造函数”异常如果我尝试直接在选择中创建。
【解决方案4】:

如果没有更多信息,很难回答这个问题,但这是您似乎想要的那种模式(除非真的有必要,否则在我的书中这将是过度设计):

public static Expression<Func<Account, bool>> GetAccountCurrencyPredicate
   (this FilterKind filter, string value)
{
    switch (filter)
    {
        case FilterKind.Exact:
            return account => account.Currency == value;

        case FilterKind.Contains:
            return account => account.Currency.Contains(value);

        case FilterKind.All:
            return account => true;

        default:
            throw new ArgumentException("Unknown FilterKind.", "filter");
    }
}

然后将其用作:

FilterKind filter = ...
string value = ...
IQueryable<Account> accounts = ...

var predicate = filter.GetAccountCurrencyPredicate(value);
var matchingAccounts = accounts.Where(predicate); 

【讨论】:

  • 我同意..过度设计!我只是想找到一个“%”等价物,所以我可以选择一个或全部!
【解决方案5】:

你不能只过滤一个条件吗?

var selectedAccounts = accounts.Select(y => y);
if(!string.IsNullOrEmpty(currency))
{
     selectedAccounts = selectedAccounts.Where(y => y.Currency.Contains(currency));
}

您甚至可以尝试更通用的版本:

IEnumerable<Account> GetAccounts(Func<Account, bool> filter)
{
    var selectedAccounts = accounts.Select(y => y);
    if(filter != null)
    {
        selectedAccounts = selectedAccounts.Where(filter);
    }
    return selectedAccounts;
}

IEnumerable<Account> GetAccountsForCurrency(string currency)
{
    if(string.IsNullOrEmpty(currency))
    {
         return GetAccounts(null);
    }
    return GetAccounts((y) => y.Currency.Contains(currency));
}

现在您有了一种更具体和更通用的方法,可用于不同类型的过滤。

【讨论】:

  • 这比用 ?: if 语句将条件放在 where 中更易读。
  • Ehh... 怎么不那么可读了?我认为将这种逻辑放在查询中会使查询的可读性降低,所以我完全不同意你的看法。此外,如果你将它包装在一个方法中,就像你应该做的那样,就像 Joaquin 在另一个答案中所做的那样,它比将逻辑放在 where 语句中更具可读性。
【解决方案6】:

如果你想返回任何东西,为什么要使用where 语句? where 用于过滤,所以如果你想返回任何东西,你可以尝试

from a in accounts
select a

或者,如果你想在其中有一个 where 语句

from a in accounts
where 1 = 1
select a

或者,如果你想要一个类似的声明,我建议使用正则表达式

from a in accounts
let r = new Regex("expression")
where r.IsMatch(a.currency)
select a;

【讨论】:

  • 他有时想使用 where 语句进行过滤。这是完全有效的,如果简单可以使用 if 语句(如我的回答)或通过将条件 Func 传递给 .Where()
  • where 1 = 1 不会编译,where 1 == 1where true 会,但没有意义。
  • @Korayem,这不是 LINQ to 对象,所以使用正则表达式是行不通的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多