EF Core では、現状 json_value をそのまま使えないですが、どうしても json_value を使いたい用事があったので、出来るように実装しました。
やり方
- 生の SQL を書く
- DbFunctions で関数呼び出しを追加する
1番なら何でもできますが、今回は、もうちょっと EF Core を活用したいので、2 番で実装します。
実装する
まず DbFunction を定義します。
public static class DBFunctions { public static string JsonValue(string column, string path) { throw new NotSupportedException(); } }
次に、DbContext を組み立てる OnModelCreating
で先ほど定義した DbFunction をセットします。
下記のコードは、文字列を返すようにする設定です
modelBuilder.HasDbFunction(typeof(DBFunctions).GetMethod(nameof(DBFunctions.JsonValue))) .HasTranslation(args => new SqlFunctionExpression("JSON_VALUE", args, nullable: true, argumentsPropagateNullability: new[] { false, false }, typeof(string), null));
日付型を返したいといった場合は、以下のような感じ
modelBuilder.HasDbFunction(typeof(DBFunctions).GetMethod(nameof(DBFunctions.JsonValueDateTime))) .HasTranslation(args => new SqlFunctionExpression("JSON_VALUE", args, nullable: true, argumentsPropagateNullability: new[] { false, false }, typeof(DateTime), null));
使い方は、以下のような感じ
var customer = await _dbContext .Customer .Where(_ => DBFunctions.JsonValue(_.Value, "$[0].name") != null) .Select(_ => new { name = DBFunctions.JsonValue(_.Value, "$[0].name") }) .ToListAsync();
このコードを実行すると、下記のような SQL に展開されます。
SELECT JSON_VALUE([c].[Value], N'$[0].name') AS [name] FROM [customer] AS [c] WHERE JSON_VALUE([c].[Value], N'$[0].name') IS NOT NULL
まとめ
EF Core 7 では、いい加減 json column が対応するみたいなので、一時しのぎですがこれにて一件落着