问题
select *
from bis.CompanyInfo ci
where ci.IsDeleted = 0
and ci.IsBindingApproved = 1
and ((ci.[Name] like N'%blah%'
or ci.CityName like N'%blah%')
or (ci.[Name] like N'%groupe%'
or ci.CityName like N'%groupe%'))
Consider that "blah" and "groupe" are keywords that I must search for. The number of keywords to search for is variable, that is where it needs to be dynamic. So, I could have any number of keywords to look for from 0 to hundreds.
Any help is appreciated! =)
回答1:
var result = (from oCompanyInfo as CompanyInfo in CompanyInfoList
where oCompanyInfo.IsDeleted = 0 and oCompanyInfo.IsBindingApproved = 1 and
(Name.Contains("blah") or oCompanyInfo.CityName.Contains("blah") or
oCompany.Name.Contains("groupe") or oCompany.CityName.Contains("groupe"))
select oCompanyInfo).ToList()
There you can replace "blah" or "groupe" to txtCompanyName.Text and txtCityName.text (if the filter text is in a textbox)
回答2:
It seems like there is an order or the-like to join the inner filter. Let's take this code as the initial from my CreateFilter method.
private Expression<Func<CompanyInfo, bool>>
CreateFilter(SearchCriterion criterion) {
var outerFilter = PredicateBuilder.True<CompanyInfo>();
outerFilter = outerFilter.And(ci => !ci.IsDeleted && ci.IsBindingApproved);
var innerFilter = PredicateBuilder.False<CompanyInfo>();
foreach(var keyword in criterion.Keywords) {
var w = keyword;
innerFilter = innerFilter.Or(ci => ci.Name.Contains(w)
|| ci.CityName.Contains(w))
}
outerFilter = outerFilter.And(innerFilter);
if (criterion.HasCityName)
outerFilter = outerFilter.And(ci =>
ci.CityName.Contains(criterion.CityName));
// Other similar filter here...
return outerFilter;
}
This was not returning the right results. Then, per this article: LINQ: Complicated Advanced Search with Dynamic Where Clause, I changed my code.
private Expression<Func<CompanyInfo, bool>>
CreateFilter(SearchCriterion criterion) {
var innerFilter = PredicateBuilder.False<CompanyInfo>();
foreach(var keyword in criterion.Keywords) {
var w = keyword;
innerFilter = innerFilter.Or(ci => ci.Name.Contains(w)
|| ci.CityName.Contains(w))
}
var outerFilter = PredicateBuilder.True<CompanyInfo>();
outerFilter = outerFilter.And(ci => !ci.IsDeleted && ci.IsBindingApproved);
if (criterion.HasCityName)
outerFilter = outerFilter.And(ci =>
ci.CityName.Contains(criterion.CityName));
// Other similar filter here...
// Here, we want to include the filter on keywords only when there are
// some provided with the search.
// Otherwise, the result of the And(innerFilter) with no keywords
// will always be 'false' and return no results though other criterion
// might be met such as the CityName and whatever the others are.
if (criterion.HasKeywords) outerFilter = outerFilter.And(innerFilter);
return outerFilter;
}
And it works flawlessly! I don't really understand why the results are perfect only as it appears the order of the filters impacts the results, and this worked for me.
来源:https://stackoverflow.com/questions/8978174/how-would-this-query-translate-into-a-dynamic-linq-expression