3

顧客が指定した特定の基準に基づいて結果を返すことができるメソッドがクラスにあります。このメソッドは、顧客がフロントエンドで指定したものを、データベースから取得したコレクション内の各アイテムと照合します。顧客がどの属性も指定しない場合、属性のIDは0に等しいメソッドに渡されます(データベースには、1でシードされ、増分であるすべてのテーブルのIDがあります)。この場合、その属性は無視する必要があります。たとえば、顧客が場所を指定しない場合、customerSearchCriteria.LocationID=0がメソッドに入ります。次に、一致は他の属性と一致し、他の属性に一致するすべての場所を返します(以下の例)。

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{   
    if(customerSearchCriteria.LocationID == 0)
    {         
         return repository.GetAllPetsLinkedCriteria()
                     .Where(x => x.TypeID == customerSearchCriteria.TypeID &&
                                 x.FeedingMethodID == customerSearchCriteria.FeedingMethodID &&
                                 x.FlyAblityID == customerSearchCriteria.FlyAblityID )
                     .Select(y => y.Pet);
    }
}

すべての基準が指定されている場合のコードを以下に示します。

private PetsRepository repository = new PetsRepository();

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{            
    return repository.GetAllPetsLinkedCriteria()
                     .Where(x => x.TypeID == customerSearchCriteria.TypeID &&
                                 x.FeedingMethodID == customerSearchCriteria.FeedingMethodID &&
                                 x.FlyAblityID == customerSearchCriteria.FlyAblityID &&
                                 x.LocationID == customerSearchCriteria.LocationID )
                     .Select(y => y.Pet);
}

顧客が探している結果の属性を明示的に選択しないたびに対応するifおよびelseステートメントのセット全体を避けたいと思います。これを達成するための最も簡潔で効率的な方法は何ですか?

4

3 に答える 3

2

選択されていない基準は常にゼロですよね?では、フィールドが基準に等しいか、基準がゼロに等しい行を取得するのはどうでしょうか。

これはうまくいくはずです

private PetsRepository repository = new PetsRepository();

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{
    return repository.GetAllPetsLinkedCriteria()
                     .Where(x => (customerSearchCriteria.TypeID == 0 || x.TypeID == customerSearchCriteria.TypeID)&&
                                 (customerSearchCriteria.FeedingMethodID == 0 || x.FeedingMethodID == customerSearchCriteria.FeedingMethodID) &&
                                 (customerSearchCriteria.FlyAblityID == 0 || x.FlyAblityID == customerSearchCriteria.FlyAblityID) &&
                                 (customerSearchCriteria.LocationID == 0 || x.LocationID == customerSearchCriteria.LocationID))
                     .Select(y => y.Pet);
}

あるいは、これが自分で多くのことをWhereしていることに気付いた場合は、基準を適用するか、ゼロの場合はパススルーする代替の拡張メソッドを作成し、基準とedを使用して1つの条件を設定する代わりに、呼び出しをチェーンすることができます。次に、一致しない行ごとではなく、クエリごとに1回だけ基準==0の比較を行います。パフォーマンスをわずかに向上させるだけの価値があるかどうかはわかりません。パフォーマンスを向上させたい場合は、データベースにフィルターを適用することをお勧めします。
とにかく、これは啓蒙の目的のためです。。。

static class Extns
{
    public static IEnumerable<T> WhereZeroOr<T>(this IEnumerable<T> items, Func<T, int> idAccessor, int id)
    {
        if (id == 0)
            return items;
        else
            return items.Where(x => idAccessor(x) == id);
    }
}

private PetsRepository repository = new PetsRepository();

public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{
    return repository.GetAllPetsLinkedCriteria()
        .WhereZeroOr(x => x.TypeID, customerSearchCriteria.TypeID)
        .WhereZeroOr(x => x.FeedingMethodID, customerSearchCriteria.FeedingMethodID)
        .WhereZeroOr(x => x.FlyAblityID, customerSearchCriteria.FlyAblityID)
        .WhereZeroOr(x => x.LocationID, customerSearchCriteria.LocationID);
}
于 2012-11-11T09:12:13.110 に答える
2

ストアド プロシージャを使用しているようで、最初にすべてのレコードを取得してからフィルタリングを行っています。ストアド プロシージャ レベルでフィルター処理を行うことをお勧めします。これにより、データベースに面倒な作業を任せることができます。後で実行する必要があるマイクロ フィルター処理が簡単になります。sproc では、params のデフォルトを NULL にし、基準オブジェクトに対してプロパティを null 可能にします。これにより、値を渡すだけで、sproc はこれらの null 値で動作するように修正されます。

 private PetsRepository repository = new PetsRepository();

    public IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
    {
        return repository.GetAllPetsLinkedCriteria(customerSearchCriteria.TypeID,customerSearchCriteria.FeedingMethodID,customerSearchCriteria.FlyAblityID,customerSearchCriteria.LocationID).ToList();
    }
于 2012-11-11T09:21:56.550 に答える
2

私はエレガントな解決策を見ていません。これかもしれません:

IEnumerable<Pet> FindPetsMatchingCustomerCriteria(CustomerPetSearchCriteria customerSearchCriteria)
{
    return repository.GetAllPetsLinkedCriteria()
                     .Where(x => 
                      Check(x.TypeID, customerSearchCriteria.TypeID) &&
                      Check(x.FeedingMethodID, customerSearchCriteria.FeedingMethodID) &&
                      Check(x.FlyAblityID, customerSearchCriteria.FlyAblityID) &&
                      Check(x.LocationID, customerSearchCriteria.LocationID))
                     .Select(x => x.Pet);
}

static bool Check(int petProperty, int searchCriteriaProperty)
{
    return searchCriteriaProperty == 0 || petProperty == searchCriteriaProperty;
}
于 2012-11-11T10:13:05.840 に答える