1

您好,感谢您花时间回答我的问题。

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

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

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

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

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

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

ETC..

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

4

3 回答 3

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);
        }
    }
}
于 2012-12-05T10:36:51.490 回答
1

是的,有可能。最简单的方法是使用委托,尤其是匿名委托。

例如:

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);
于 2012-12-05T10:36:25.600 回答
1

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

LINQ to Entities:组合谓词

然后,您可以像这样构建 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);
}
于 2012-12-05T10:36:58.057 回答