Sim*_*ons 5 .net c# linq expression linq-to-sql
我正在使用LINQ exprssion来查询客户并按州名称过滤它们。我有以下查询,在我的statesArray中有4个项目之前,它运行良好。
public void GetCustomersForSelectedStates(string[] statesArray)
{
var customers = _repo.GetAllCustomers();
var filteredCustomers = from CUST in customers
join ST in States on CT.Tag_Id equals ST.Id
where CUST.ID == customer.ID && (ST.Name == statesArray[0] ||ST.Name ==statesArray[1] || ST.Name== statesArray[2]||ST.Name =statesArray[3])
//Do something with customers
}
Run Code Online (Sandbox Code Playgroud)
我想动态创建以下表达式:
(ST.Name == statesArray[0] ||ST.Name ==statesArray[1] ||
ST.Name== statesArray[2]||ST.Name =statesArray[3])
Run Code Online (Sandbox Code Playgroud)
例如,创建如下的dynamicQuery
var dynamicQuery = "(";
var dynamicQuery = "(";
for (int i = 0; i < statesArray.Count(); i++)
{
dynamicQuery += "ST.Name =="+statesArray[0];
if(i==statesArray.Count())
dynamicQuery+=")"
}
Run Code Online (Sandbox Code Playgroud)
然后像下面这样使用它,
//Psuedo code
var customers = _repo.GetAllCustomers();
var filteredCustomers = from CUST in customers
join ST in States on CT.Tag_Id equals ST.Id
where CUST.ID == customer.ID && Expression(dynamicQuery)
Run Code Online (Sandbox Code Playgroud)
To do that via dynamic expressions basically means building a tree of:
(x.Foo == val0 || x.Foo == val1 || x.Foo == val2)
Run Code Online (Sandbox Code Playgroud)
You can do that like this:
static Expression<Func<T, bool>> Where<T, TVal>(Expression<Func<T, TVal>> selector,
IEnumerable<TVal> values)
{
Expression result = null;
foreach (var val in values)
{
var match = Expression.Equal(
selector.Body,
Expression.Constant(val, typeof(TVal)));
result = result == null ? match : Expression.OrElse(result, match);
}
if (result == null) return x => true; // always match if no inputs
return Expression.Lambda<Func<T, bool>>(result, selector.Parameters);
}
Run Code Online (Sandbox Code Playgroud)
with example usage:
string[] names = { "a", "c" };
var predicate = Where<Customer, string>(c => c.Name, names);
Run Code Online (Sandbox Code Playgroud)
You can then use this predicate in the IQueryable<T>.Where extension method.
To combine it in your case, first do your regular LINQ:
var customers = _repo.GetAllCustomers();
var filteredCustomers = from CUST in customers
join ST in States on CT.Tag_Id equals ST.Id
where CUST.ID == customer.ID;
Run Code Online (Sandbox Code Playgroud)
Now as a separate step apply the extra filter:
customers = customers.Where(predicate);
Run Code Online (Sandbox Code Playgroud)
What this does is accept an input lambda of the form c => c.Name, then reuses the c.Name body for each c.Name == {val}, and reuses the c parameter as the parameter for the lambda we're creating. Each value from values becomes a typed constant. The Expression.Equal gives us the == test. The OrElse is the ||, noting that if result is null, this is the first item, so we just use the match expression itself.
| 归档时间: |
|
| 查看次数: |
487 次 |
| 最近记录: |