1

こんにちは、私の質問に答えるために時間を割いてくれてありがとう。

Javaでの作業の1年半後、私は.NETに戻すことにしました。私はVS2012でくつろいでいると言わなければなりません。

Javaを使用しているときに、動的クエリを簡単に作成できるHibernateの実装に出くわしました。

結果をフィルタリングするために、5つのフィールドがあり、そのうちの1つだけを入力する必要があるフォームがあるとします。

C#で次のことを実行できる方法はありますか?

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

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

等..

したがって、すべてのフィールドをチェックし、値が入力されている場合は、その基準をクエリに追加します。チェックが完了したら、クエリを実行します。C#でこれを行う方法はありますか?

4

3 に答える 3

2

これを行う最も簡単な方法は、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: 述語の組み合わせ

次に、次のようなラムダ式を作成できます。

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 に答える