1

どこでリストを使用することは可能ですか?私はこのようなことを考えたい:

public class Customer
{
    string FirtsName;
    string LastName;
    int Number;
    .....
}

チェックボックスを使用して顧客をフィルタリングしたい。FirstNameとNumberを選択すると、where句が生成されます

.where(x=> x.FirstName == "SomeFirstName" && x.Number == someNumber)

番号のみを選択すると、where句が生成されます

.where(x.Number == someNumber)

FirstName、LastName、Numberを選択すると、where句が生成されます

.where(x=> x.FirstName == "SomeFirstName" && x.Number == someNumber && x.LastName == "LastName")

つまり、動的な列名だけでなく、where句も重要なものを生成したいと思います。列の名前と値はリストから取得されます。

説明できるといいのですが。前もって感謝します。

4

4 に答える 4

4

複数のステップを使用してクエリを生成します。

var query = originalList.AsQueryable();

if(/*Filtering on First Name*/)
{
  query = query.where(x => x.FirstName == FirstNameSearchString);
}

if(/*Filtering on Last Name */)
{
  query = query.where(x => x.LastName == LastNameSearchString);
}

if(/*Filtering on Number*/)
{
  query = query.where(x => x.Number== NumberSearchString);
}

//..And so on

//Do stuff with query

複数の if ステートメントを実行したくない場合は、他に 2 つの方法を考えることができます。

  • 独自の式ツリーを手動で構築します。

式ツリー (C# および Visual Basic) 方法: 式ツリーを使用して動的クエリを構築する (C# および Visual Basic)

もう 1 つの方法は、AND と OR を使用して、この列検索オプションが選択されている場合にのみフィルタリングする複雑な where 句を作成することです。

.where(x => (IsFirstNameFilter == true && x.FirstName = FirstNameData) || (IsLastNameFilter == true && x.LastName = LastNameData) || ...);

これで、実行時間に注意したいので、SQL Profiler を接続して何が起こっているかを確認します。

私はまだ最初のオプションをお勧めします。

于 2012-12-14T14:59:53.333 に答える
1

型の安全性が失われるため、文字列の使用は避けます。代わりに、式ツリーを使用して、where句の式を作成します。

        //The variable name for the parameter expression must match in all others
        var parameter = Expression.Parameter(typeof(Customer),"c");

        Expression<Func<Customer,bool>> firstNameCheck = c => c.FirstName == FirstNameSearchString;            
        Expression<Func<Customer,bool>> lastNameCheck = c => c.LastName == LastNameSearchString;
        Expression<Func<Customer,bool>> numberCheck = c => c.Number.ToString() == NumberSearchString;

        //Default to a true expression
        Expression ongoingExpression = Expression.Constant(true);

        if (//Filter on first name)
        {
            ongoingExpression = Expression.AndAlso(ongoingExpression, Expression.Invoke(firstNameCheck, parameter));
        }

        if (//Filter on last name)
        {
            ongoingExpression = Expression.AndAlso(ongoingExpression, Expression.Invoke(lastNameCheck, parameter));
        }

        if (//Filter on number)
        {
            ongoingExpression = Expression.AndAlso(ongoingExpression, Expression.Invoke(numberCheck, parameter));
        }



        var lambda = Expression.Lambda<Func<Customer, bool>>(ongoingExpression, parameter);            

        query = query.Where(lambda.Compile());
于 2012-12-14T21:24:56.703 に答える
1

上記の(最初の提案の)回答は良いと思います-現在のアーキテクチャで同じことを効果的に行っていますが、基本的に2つの部分にもう少しまとめられています:

  1. 私はフィルタークラスを持っています(関連するエンティティに固有です...あなたの場合、おそらく「CustomerFilter」と呼ばれます)このクラスには、次のようなメソッドがあります(単なる例)

    public class CustomerFilters
    {
        public IEnumerable<Expression<Func<Customer, bool>>> Filters()
        {
            if (/*check if should filter on FirstName here*/)
            {
                yield return cust => cust.FirstName == FirstNameSearchString;
            }
            if (/*check if should filter on Surname here*/)
            {
                yield return cust => cust.Surname == SurnameSearchString;
            }
        }
    }
    
  2. 基本的にすべてのフィルターをループし、そこから where を構築する拡張メソッド (ヘルパーとして、必ずしも拡張メソッドである必要はありません) があります。コードは次のようになります (多かれ少なかれ):

    public static IQueryable<T> Filter<T>(this IQueryable<T> collection, IEnumerable<Expression<Func<T, bool>>> filters)
    {
        var results = collection;
        foreach (var f in filters)
        {
            results = results.Where(f);
        }
        return results;
    }
    

次に、その使用法は次のようになります。

var query = db.Customers.Filter(myCustomerFilterClass.Filters());

私が言うように、それは前の回答と同じことになります (そして、ここでは簡潔にするために多くのコードを単純化しました)。多数のエンティティに多数のフィルターがあり、適用される特定のフィルターがユーザー主導であるアプリケーション。

于 2012-12-14T20:19:39.217 に答える
1

Dynamic LINQを試すことができます。これを使用すると、次のように書くことができます。

var db = new NorthwindDataContext;
var query = db.Products.Where("CategoryID=2 And UnitPrice>3").OrderBy("SupplierId");
于 2012-12-14T15:55:12.183 に答える