动态构建查询

时间:2012-12-05 10:24:30

标签: c# .net linq dynamic

嗨,谢谢你抽出时间回答我的问题。

在使用Java一年半之后,我决定切换回.NET。我必须说在VS2012中我有宾至如归的感觉。

在使用Java时,我遇到了一个hibernate实现,它可以轻松创建动态查询。

想象一下,我有一个包含5个字段的表单,其中只有一个字段必须填充,以便我按照过滤结果。

有没有办法在C#中执行以下操作:

if(txtMunicipality.text.length > 0){
   (x => x.municipality == txtMunicipality.text)
}

if(chkboxIsFinished){
   (x => x.isfinished == true)
}

等。

所以我ccheck每个字段,如果已填充该值,则将该条件添加到查询中...在完成检查后,我执行查询。有没有办法在C#中做到这一点?

3 个答案:

答案 0 :(得分:2)

最简单的方法是编写两个查询,即

IQueryable<Foo> query = ... // or possibly IEnumerable<Foo>
if(!string.IsNullOrEmpty(txtMunicipality.text)) {
    query = query.Where(x => x.municipality == txtMunicipality.text);
}
if(chkboxIsFinished) {
    query = query.Where(x.isfinished);
}

可以也直接组成表达式树和委托;如果您需要,请说明您拥有的内容:表达式树与委托人。


编辑:这是你如何编写表达式而不是查询:

static class Program
{
    static void Main()
    {
        Expression<Func<int, bool>> exp1 = x => x > 4;
        Expression<Func<int, bool>> exp2 = x => x < 10;
        Expression<Func<int, bool>> exp3 = x => x == 36;

        var combined = (exp1.AndAlso(exp2)).OrElse(exp3);
        // ^^^ equiv to x => (x > 4 && x < 10) || x == 36
    }
    static Expression<Func<T, bool>> OrElse<T>(this Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
    {   // trivial cases
        if (x == null) return y;
        if (y == null) return x;

        // rewrite using the parameter from x throughout
        return Expression.Lambda<Func<T, bool>>(
            Expression.OrElse(
                x.Body,
                SwapVisitor.Replace(y.Body, y.Parameters[0], x.Parameters[0])
            ), x.Parameters);
    }
    static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> x, Expression<Func<T, bool>> y)
    {   // trivial cases
        if (x == null) return y;
        if (y == null) return x;

        // rewrite using the parameter from x throughout
        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(
                x.Body,
                SwapVisitor.Replace(y.Body, y.Parameters[0], x.Parameters[0])
            ), x.Parameters);
    }
    class SwapVisitor : ExpressionVisitor
    {
        public static Expression Replace(Expression body, Expression from, Expression to)
        {
            return new SwapVisitor(from, to).Visit(body);
        }
        private readonly Expression from, to;
        private SwapVisitor(Expression from, Expression to)
        {
            this.from = from;
            this.to = to;
        }
        public override Expression Visit(Expression node)
        {
            return node == from ? to : base.Visit(node);
        }
    }
}

答案 1 :(得分:1)

是的,有可能。最简单的方法是 delegates ,尤其是匿名的。

例如:

Func<YourEntity, bool> filter = (_ => true); // Default value.

if (txtMunicipality.text.length > 0)
{
    filter = (x => x.municipality == txtMunicipality.text);
}
else if (chkboxIsFinished)
{
    filter = (x => x.isfinished == true);
}

然后你可以在查询中使用filter委托,例如在Where声明中(我认为这是你的意图 - 如果没有,该示例仍然相关,只是不直接适用)

/ LINQ syntax.
var entities = from e in context
               where filter(e)
               select e;

// Method syntax.
var entities = context.Where(x => filter(x));
// Or simply:
var entities = context.Where(filter);

答案 2 :(得分:1)

在本文中,您可以找到一些有用的扩展方法,它们允许您组合谓词(它也适用于NHibernate):

LINQ to Entities: Combining Predicates

然后你可以构建一个这样的lambda表达式:

Expression<Func<MyObject, bool>> predicate = x => true;

if(txtMunicipality.text.length > 0){
   predicate = predicate.And(x => x.municipality  == txtMunicipality.text);
}

if(chkboxIsFinished){
   predicate = predicate.And(x => x.isfinished == true);
}
相关问题