Linq Contains to return ALL items or selected ones?
Is it possible to write a linq select with a where 开发者_如何学Goclause which can select either ALL items or specific ones? In SQL I could use "where currency like '%'" to return everything. I am trying to write a method so I can pass in the currency (amongst a few other things) and re-use the same method.
e.g.
Just GBP
from a in accounts
where currency.Contains('GBP')
select a
Just GBP
from a in accounts
where currency == 'GBP'
select a
ALL currencies?
from a in accounts
where currency like '%'
select a
Have you tried to "store" the query and filter it in a later step, like so:
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;
}
This could be collapsed in a single query, but seems less readable to me and may not work with LINQ-to-SQL (or other LINQ-to-DB where the expression is translated to a query):
from a in accounts
where string.IsNullOrEmpty(filter) || a.Currency.Contains(filter)
select a
You could try
.Where(c => currencyToFind == null ? true : c==currencyToFind)
And pass in a null for the currency you want if you want them all.
In a linq query expression:
from a in accounts
where (currencyToFind == null ? true : account.Currency==currencyToFind)
select a
If you want to return all currencies, just don't use any where
(both in LINQ and SQL):
from a in accounts
select a
Or, if you really don't need to do anything else, just use accounts
.
EDIT: If you want to have one method, and, say, any currency is represented by null
, you could do it like this:
IQueryable<Account> result = accounts;
if (currency != null)
result = result.Where(a => a.Currency == currency);
return result;
It's hard to answer this without more information, but here's the sort of pattern that you appear to want (this would be overengineering in my book unless really warranted):
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");
}
}
And then use it as:
FilterKind filter = ...
string value = ...
IQueryable<Account> accounts = ...
var predicate = filter.GetAccountCurrencyPredicate(value);
var matchingAccounts = accounts.Where(predicate);
Can't you just filter on a condition?
var selectedAccounts = accounts.Select(y => y);
if(!string.IsNullOrEmpty(currency))
{
selectedAccounts = selectedAccounts.Where(y => y.Currency.Contains(currency));
}
You could even try an even more generic version:
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));
}
Now you have one more specific and one more general method that could be used for different types of filtering.
Why are you using a where
statement if you want to return anything?
where
is made for filtering, so if you want to return anything you can either try
from a in accounts
select a
or, if you want to have a where statement in it
from a in accounts
where 1 = 1
select a
or, if you want a like statement i suggest using a regex
from a in accounts
let r = new Regex("expression")
where r.IsMatch(a.currency)
select a;
精彩评论