.NET Core 3.1対応をしているのですが、それに伴ってEntity Framework Coreもv3にあげたところ、LINQのクライアントサイド評価が行われなくなったことでいくつかのクエリが使えなくなったため、いろいろ調べながら対応しています。
対応が必要だったうちの一件が下記のようなもの。
class TBL {
string Data1;
string Data2;
}
このようなクラスを保持するリスト(List
.Where(x => list.Any(l => l.Data1 == x.Data1 && l.Data2 = x.Data2))
のように、含まれている値と一致するレコードだけを取得するというものです。
SQLにしてみれば
WHERE
(TBL.Data1 == [listの値1-1] && TBL.Data2 == [listの値1-2])
OR (TBL.Data1 == [listの値2-1] && TBL.Data2 == [listの値2-2])
・・・
みたいな感じ。
LINQ to SQLだとこのクエリ、SQLに変換してサーバーサイドで実行してくれないんですね。
式木をうまいことこねこねして動的に.Where内の値を生成するようにしようと思ったのですが、今の力量だとちょっと手間取りそうで、それに時間をかけてられないこともあり、とりあえずLINQを使わずFromSqlRawで直接SQLを実行することにしました。
SQLで実行するにしてもWHERE句に指定する条件はリストから動的に生成する必要があります。
そんな時に便利なのが下記のLINQ。
var param = list
.Aggregate(
string.Empty,
(current, tbl) => current + $" OR ([Data1] = '{tbl.Data1}' AND [Data2] = {tbl.Data2}) ");
これならlistに格納されている値分のOR条件式が一つの文字列に吐き出されるので、あとは
var sql = $@"SELECT * FROM TBL
WHERE (1=0)
{param}";
こんな感じでSQLにぶち込んで、EFなりDapperなりに渡してやればOK。