LinqPadを使用して基本的な動的Linqクエリを作成しようとしています。私の方法では、ユーザーに1〜3個のオプションを選択するように求め、その入力に基づいてクエリを動的に作成します。
public void FilteredPropertySearch()
{
bool addAnotherOption = true;
int option;
Dictionary<int, bool> parameters = new Dictionary<int, bool>();
var predicate = PredicateBuilder.False<ResidentialProperty>();
Console.WriteLine("Follow instructions to filter property search results");
do
{
// get user input
option = int.Parse(Console.ReadLine());
switch(option)
{
case 1:
parameters.Add(1, true);
break;
// more cases - when case 0 addAnotherOption = false, loop ends
default:
Console.WriteLine("That was not a valid option");
break;
}
}while(addAnotherOption == true);
foreach(KeyValuePair<int, bool> p in parameters)
{
if(p.Key == 1 && p.Value == true)
predicate = predicate.Or (c => c.HasBackGarden);
if(p.Key == 2 && p.Value == true)
predicate = predicate.Or (c => c.HasFrontGarden);
if(p.Key == 3 && p.Value == true)
predicate = predicate.Or (c => c.HasSecureParking);
}
ResidentialProperties.Where (predicate).Dump();
}
foreach
ループはユーザーの入力に基づいてクエリを作成する必要がありますが、たとえば、ディクショナリの最初の値をtrueにして他の値を選択しないと、結果が返されません。私の知っているように、データベーステーブルには、 Key(1)
がtrueである値がいくつかあります。
if
がforeach
の後にquery
他のことをする必要がありquery
か?
編集
私の代わりに、述語ビルダーを使ってきたし、私が使用した場合の作業(の一種)であるように思わpredicate.Or
(編集済みのコードごとなど)を、それが唯一の私が選択していることを最初のオプションを返し、それは式ツリーを構築していません。 predicate.Or
をpredicate.And
変更すると、選択した各ユーザー入力がフィルター式に追加されます。
ユーザーが3つのオプションをすべて選択した場合、列HasBackGarden、HasFrontGarden、およびHasSecureParkingがtrueである行のみが返されるようにします。どうすればこれを達成できますか?
結果セットをすべての条件を満たすレコードに制限する場合は、 .And
代わりに.Or
使用する必要がありますが、これを行うには、 PredicateBuilder.True<ResidentialProperty>()
開始する必要がありますPredicateBuilder.True<ResidentialProperty>()
False
ではなく。
これは、フィルターが追加される前に、正しい結果セットにすべてのレコードが含まれ、後続の各フィルターが結果セットを制限するためです。 False
から始めると、どのレコードも述部を満たすことができません。
あなたのコードから、それはあなたが空の列挙可能なvar "query"で操作しているように見えます。クエリと呼ばれるのはデータセットであり、Whereステートメントはそのデータセットに対するクエリです。したがって、最初のクエリは空のデータセットに対して行われ、foreachからの追加のクエリはその空のセットを調整するだけのようです。
また、これらはブール値なので、.Where(q => q.HasWhatever)を実行できます。