Soma 0.10.1.0 リリース

F#で作ったO/Rマッパー Soma 0.10.1.0をリリースしました(F#はもちろんC#VB.NETでも使えます)。ぜひお試しください。

Release Notes
  • New Feature - プロパティが大文字小文字を区別しない動的オブジェクトの作成をサポートしました。
  • Change - 式コメント内でIDictionaryに対するインデクサ経由のアクセスをサポートしました。
  • Change - xxxWithoutVersion メソッド/関数をInsertOpt/UpdateOpt/DeleteOptクラスをパラメータにもつ新しいメソッド/関数に置き換えました。
  • Change - プロパティを持たない匿名型を問い合わせ条件の引数に使用することを認めました。 (C#, VB.NET)
  • Change - 問い合わせ条件の匿名型が動的オブジェクトをプロパティに持つことを認めました。 (C#, VB.NET)

以下、簡単な機能紹介です(コードはF#です)。

プロパティが大文字小文字を区別しない動的オブジェクトの作成をサポートしました

ポイントは、

  • dynamicという関数で動的オブジェクトを作れる(C#ではDynamicOperationsクラスのDynamicメソッドで作れます)
  • dynamicから返されたオブジェクトには ? 演算子で値を取得したり ?<- 演算子で値を設定できる(C#ではdynamicキーワードで受けて、ドット(.)でアクセスできます)。プロパティ名はあらかじめ定義しておく必要がなく、さらにプロパティ名は大文字小文字は区別されない。

使用例はこんな感じです。

let emp = dynamic()
emp?EmployeeName <- "King"

let empList =
MyDb.query<Employee>
"select * from Employee where EmployeeName = /* emp.EMPLOYEENAME */'smith'"
<@ let emp = emp in () @>
この例では、emp?EmployeeName <- "King" とキャメルケースの EmployeeName プロパティに値を設定していますが、SQLのバインド変数コメント内では emp.EMPLOYEENAME とすべて大文字の EMPLOYEENAME プロパティから値を取得しています。大文字小文字は区別されないので内部的には同じプロパティへのアクセスとなります。

ちなみに、問い合わせ結果を動的オブジェクトで受け取ることもできます。そうしたい場合は、関数の型パラメータにdynamicと指定します。

let empList = 
MyDb.query<dynamic>
"select * from Employee where EmployeeName = /* emp.EMPLOYEENAME */'smith'"
<@ let emp = emp in () @>
大文字小文字を区別しないのは、SQLがそうなので、相性がいいと思います。

式コメント内でIDictionaryに対するインデクサ経由のアクセスをサポートしました

上の例と似ているのですが、Stringをキーとするディクショナリを問い合わせ条件に指定して式コメント内では普通のプロパティであるかのようにアクセスできるようにしました。ただし、キー名の大文字小文字は区別されます。

let emp = new Dictionary<string, obj>()
emp.["EmployeeName"] <- "King"

let empList =
MyDb.query<Employee>
"select * from Employee where EmployeeName = /* emp.EmployeeName */'smith'"
<@ let emp = emp in () @>
ディクショナリはSystem.Collections.Generic.IDicionaryのキーの型パラメータがStringであれば、実装クラスはなんでも大丈夫です。たとえば、F#のMapとか。

xxxWithoutVersion メソッド/関数をInsertOpt/UpdateOpt/DeleteOptクラスをパラメータにもつ新しいメソッド/関数に置き換えました

特定のフィールド(プロパティ)を更新対象から除いたり含めたり、NULLのものだけ除いたり、バージョンを無視したりなどの制御をできるようにしました。例えば、以下のコードでは EmployeeName フィールド(プロパティ)だけを UPDATE の SET句に含めるように指定しています。

let emp = { EmployeeId = 0; EmployeeName = "Hoge"; DepartmentId = 1; VersionNo = 0 }
let emp = MyDb.updateWithOpt emp (UpdateOpt(Include = ["EmployeeName"]))

他の例はドキュメントを参照ください。