LINQ 正規関数にマッピングされていない Oracle 関数の使い方。
幾つか実装方法はありますが、簡単な方法から。
環境
- Visual Studio 2022
- .net 6.0
- EF Core 6.0.29
- Oracle EF Core 6.21.1.40
- NLog (ログを確認の為、出力)
実装
主要部分のみで、内容に意味は無いです。
"こうすれば動くよ!"という事を抜粋して記載します。
流れとしては以下の通りです。
.net のメソッドを定義(Oracle 関数とマッピング用)
.net のメソッドをサクッと定義
※平方根を算出する "SQRT" とマッピング予定
public static class StringExtension { public static int Sqrt(this int? value) => throw new NotImplementedException(); }
.net で定義したメソッドを Oracle 関数とマッピング
DbContext を継承し OnModelCreating を override します。
.net で定義したメソッドの MethodInfo を取得します。
HasDbFunction の引数に渡して、HasName で何の関数にマッピングするか設定。
※.net のメソッドと Oracle 関数が 1:1 なのでこれで十分
シグネチャが同じであれば、"SQRT" 以外のOracle関数でもマッピング可能。
.net のメソッドと Oracle の関数は役割が近く名前も似ていた方が把握し易くなりますね。
protected override void OnModelCreating(ModelBuilder modelBuilder) { var sqrt = typeof(StringExtension).GetMethod("Sqrt", new Type[] { typeof(int) })!; modelBuilder.HasDbFunction(sqrt).HasName("SQRT"); base.OnModelCreating(modelBuilder); }
.net のメソッドを利用し SQL を発行し結果を確認
エンティティのメンバとか全無視して期待した SQL が発行されるか確認。
// SampleNumber の値に、 2, 16, 40, 6423 が設定されたレコード有 // 平方根の結果が、3より大きく 7未満の場合 var context = new SampleDbContext(); var items = (from m in context.SampleTables where m.SampleNumber.Sqrt() > 3 && m.SampleNumber.Sqrt() < 7 select m); foreach (var item in items) { // 16 // 40 Console.WriteLine(item.SampleNumber); }
上記で発行された SQL をログ出力した結果
SELECT "s"."ID", "s"."SAMPLENUMBER" FROM "SAMPLETABLE" "s" WHERE (("SQRT"("s"."SAMPLENUMBER") > 3) AND ("SQRT"("s"."SAMPLENUMBER") < 7))
マッピングされ期待した結果が無事取得出来ました。
ユーザーが独自に定義した関数も可能だったり、
.net のメソッドと Oracle 関数を 1:n でマッピングだったり出来るので気分が向いたら追記します。