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
}
我想动态创建以下表达式:
(ST.Name == statesArray[0] ||ST.Name ==statesArray[1] ||    
 ST.Name== statesArray[2]||ST.Name =statesArray[3])
例如,创建如下的dynamicQuery
var dynamicQuery = "(";
var dynamicQuery = "(";
for (int i = 0; i < statesArray.Count(); i++)
    {
        dynamicQuery += "ST.Name =="+statesArray[0];
        if(i==statesArray.Count())
        dynamicQuery+=")"
    }
然后像下面这样使用它,
//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)
To do that via dynamic expressions basically means building a tree of:
(x.Foo == val0 || x.Foo == val1 || x.Foo == val2)
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);
}
with example usage:
string[] names = { "a", "c" };
var predicate = Where<Customer, string>(c => c.Name, names);
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;
Now as a separate step apply the extra filter:
customers = customers.Where(predicate);
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 次 | 
| 最近记录: |