2017-11-25 46 views
1

選択肢の組み合わせがあり、選択した内容に基づいてデータをフィルタリングする必要があります(この場合はEFを使用します)。すべての組み合わせをリストするのではなく、次のような記述を書く方がクリーンですか?クエリの組み合わせを組み合わせるためのLinq構文

私の最初の試みは、特に組み合わせがさらに大きくなると、あまりにも複雑に思えます。

DateTime today = DateTime.Now.Date; 
DateTime yesterday = today.AddDays(-1); 
DateTime tomorrow = today.AddDays(1); 

var query = db.Products.AsQueryable(); 
if (userSettings.DisplayYesterday && userSettings.DisplayToday && userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday || DbFunctions.TruncateTime(x.ListedTime) == today || DbFunctions.TruncateTime(x.ListedTime) == tomorrow); 
} 
else if (!userSettings.DisplayYesterday && userSettings.DisplayToday && userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == today || DbFunctions.TruncateTime(x.ListedTime) == tomorrow); 
} 
else if (userSettings.DisplayYesterday && !userSettings.DisplayToday && userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday || DbFunctions.TruncateTime(x.ListedTime) == tomorrow); 
} 
else if (userSettings.DisplayYesterday && userSettings.DisplayToday && !userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday || DbFunctions.TruncateTime(x.ListedTime) == today); 
} 
else if (!userSettings.DisplayYesterday && !userSettings.DisplayToday && userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == tomorrow); 
} 
else if (!userSettings.DisplayYesterday && userSettings.DisplayToday && !userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == today); 
} 
else if (userSettings.DisplayYesterday && !userSettings.DisplayToday && !userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday); 
} 
else if (userSettings.DisplayYesterday && !userSettings.DisplayToday && !userSettings.DisplayTomorrow) 
{ 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday); 
} 
else if (!userSettings.DisplayYesterday && !userSettings.DisplayToday && !userSettings.DisplayTomorrow) 
{ 
    // If nothing is selected then default to today 
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == today); 
} 

List<Products> productList = await query.ToListAsync(); 

答えて

3

はい、あなたはLinqKitのnugetパッケージをインストールして使用することができ、そのPredicateBuilder(何らかの理由でサードパーティのパッケージをインストールしたくない\ことができない場合 - あなたは同様の機能を自分で実装することができます)。 PredicateBuilderを使用すると、このようにそれを行うことができます。

if (someCondition) 
    query = query.Where(x => x.SomeField == someValue); 
if (anotherCondition) 
    query = query.Where(x => x.SomeAnotherField == someAnotherValue); 
+0

優れています。これは非常にクリーンです。ありがとうございました。 – pathDongle

+0

@pathDongle私は、この部分的な日付のケースについて、より良い解決策を少しは答えて更新しました(私はそう思います)。 – Evk

+0

ありがとう、私は特に日付のソリューションを探していなかった、それはちょうど組み合わせだった。私はかなり日付について自信を持って、DateTime.Nowがこの状況で正しいことを知っています。再度、感謝します。 – pathDongle

1
:AND(とないORここのように)、あなたは述語ビルダーを必要としない、ちょうど Where呼び出しをチェーン付き

// start with false, because building OR expression 
// and false OR something is the same as just something 
var condition = PredicateBuilder.New<Product>(false); 
if (userSettings.DisplayYesterday) 
    condition = condition.Or(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday); 
if (userSettings.DisplayToday) 
    condition = condition.Or(x => DbFunctions.TruncateTime(x.ListedTime) == today); 
if (userSettings.DisplayTomorrow) 
    condition = condition.Or(x => DbFunctions.TruncateTime(x.ListedTime) == tomorrow); 
query = query.Where(condition); 

あなたが複数の条件を結合する場合

Linq2Sqlでは、それは、効率的なクエリを作成するために使用されている条件のみを生成

bool dispYesterday = userSettings.DisplayYesterday; 
bool dispTomorrow = userSettings.DisplayTomorrow; 
bool dispToday = userSettings.DisplayToday || !dispYesterday && !dispTomorrow; 

query = query.Where(x => 
    dispYesterday && x.ListedTime.Date == yesterday 
|| dispToday && x.ListedTime.Date == today 
|| dispTomorrow && x.ListedTime.Date == tomorrow 
); 

を書くことができます。 EFでは、何かsimmilarを書くことができますが、生成されたSQLクエリは扱いにくく非効率ですが、それはこのフレームワークが生成するコードの大部分です。

関連する問題