目次

概要

プログラミング言語に F# を利用する場合、データベースへのアクセスは Soma.Core.Dbモジュール、または Soma.Core.LocalDbモジュールを介して行います。
プログラミング言語にC#やVB.NETを利用する場合は、 DbクラスとLocalDbクラス を参照してください。

Soma.Core.Dbモジュール と Soma.Core.LocalDbモジュール の違いは、コネクションの扱い方にあります。Soma.Core.Dbモジュール は、コネクションの生成と破棄を自動で行います。したがって、このモジュールのクライアントはコネクションを管理する必要がありません。一方、Soma.Core.LocalDbモジュール は、コネクションの生成と破棄を自動で行いません。したがって、このモジュールのクライアントはコネクションを管理しなければいけません。

どちらのモジュールを使ってもトランザクションは System.Transactions.TransactionScope を用いて制御できます。しかし、ADO.NETデータプロバイダによってはひとつのトランザクションに複数のコネクションを関連付けられません。その場合には、ひとつのトランザクションではひとつのコネクションのみを使用するようにアプリケーションで調整が必要です。Soma.Core.LocalDbモジュールは、そのような制限をもつADO.NETデータプロバイダを利用する場合に使用できます。

ひとつのトランザクションに複数のコネクションを関連付けられないという制限は、Microsoft SQL Server Compact 4.0 と SQLite 3 のデータプロバイダにあります。したがって、これらを利用する場合に Soma.Core.LocalDbクラス を使用してください。

このページで示すサンプルコードはすべてF#で記述されています。Soma.Core.DbモジュールやSoma.Core.LocalDbモジュールのqueryやexecuteといった関数ではSQLを利用可能ですが、SQLの記述の仕方については SQL記述 式言語 を参照してください。

なお、Soma.Core.Dbモジュール と Soma.Core.LocalDbモジュール のAPI は、コネクションをパラメータで渡すかどうかを除けば非常に似ています。したがって、このドキュメントでは Soma.Core.Dbモジュール を中心に説明します。

Soma.Core.Db

Soma.Core.Dbモジュールのシグネチャは以下の通りです。

シグネチャ
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Db =
  val query<'T> : config:IDbConfig -> sql:string -> condition:(string * obj * Type) list -> 'T list
  val queryOnDemand<'T> : config:IDbConfig -> sql:string -> condition:(string * obj * Type) list -> 'T seq
  val paginate<'T> : config:IDbConfig -> sql:string -> condition:(string * obj * Type) list -> offset:int64 * limit:int64 -> 'T list
  val paginateOnDemand<'T> : config:IDbConfig -> sql:string -> condition:(string * obj * Type) list -> offset:int64 * limit:int64-> 'T seq
  val paginateAndCount<'T> : config:IDbConfig -> sql:string -> condition:(string * obj * Type) list -> offset:int64 * limit:int64 -> 'T list * int64
  val execute : config:IDbConfig -> sql:string -> condition:(string * obj * Type) list -> int  
  val executeReader<'T> : config:IDbConfig -> handler:(DbDataReader -> 'T) -> sql:string -> condition:(string * obj * Type) list -> 'T
  val find<'T when 'T : not struct> : config:IDbConfig -> idList:obj list -> 'T
  val tryFind<'T when 'T : not struct> : config:IDbConfig -> idList:obj list -> 'T option
  val findWithVersion<'T when 'T : not struct> : config:IDbConfig -> idList:obj list -> version:obj -> 'T
  val tryFindWithVersion<'T when 'T : not struct> : config:IDbConfig -> idList:obj list -> version:obj -> 'T option
  val insert<'T when 'T : not struct> : config:IDbConfig -> entity:'T -> 'T
  val insertWithOpt<'T when 'T : not struct> : config:IDbConfig -> entity:'T -> opt:InsertOpt -> 'T
  val update<'T when 'T : not struct> : config:IDbConfig -> entity:'T -> 'T
  val updateWithOpt<'T when 'T : not struct> : config:IDbConfig -> entity:'T -> opt:UpdateOpt -> 'T
  val delete<'T when 'T : not struct> : config:IDbConfig -> entity:'T -> unit
  val deleteWithOpt<'T when 'T : not struct> : config:IDbConfig -> entity:'T -> opt:DeleteOpt -> unit
  val call<'T when 'T : not struct> : config:IDbConfig -> procedure:'T -> 'T


これらの各関数については、このページでそれぞれ詳細を説明します。

Soma.Core.Dbモジュールの典型的な使い方を以下に示します。

典型的な利用例
  use tx = new TransactionScope()

  let emp = Db.find<Employee> config [1]
  let emp = Db.update config { emp with EmployeeName = "Hoge" }
  Db.delete config emp

  tx.Complete()

この例のポイントを説明します。
  • トランザクションは System.Transactions.TransactionScopeクラスを用いて制御します。
  • Soma.Core.Dbモジュールの第一引数は 設定 のインスタンスです。毎回第一引数に指定するのは煩雑なので関数の部分適用をしておくとよいでしょう。

Soma.Core.LocalDb

Soma.Core.LocalDbモジュールのシグネチャは以下の通りです。

シグネチャ
[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module LocalDb =
  val query<'T> : config:IDbConfig -> connection:DbConnection -> sql:string -> condition:(string * obj * Type) list  -> 'T list
  val queryOnDemand<'T> : config:IDbConfig -> connection:DbConnection -> sql:string -> condition:(string * obj * Type) list  -> 'T seq
  val paginate<'T> : config:IDbConfig -> connection:DbConnection -> sql:string -> condition:(string * obj * Type) list -> offset:int64 * limit:int64 -> 'T list
  val paginateOnDemand<'T> : config:IDbConfig -> connection:DbConnection -> sql:string -> condition:(string * obj * Type) list  -> offset:int64 * limit:int64-> 'T seq
  val paginateAndCount<'T> : config:IDbConfig -> connection:DbConnection -> sql:string -> condition:(string * obj * Type) list  -> offset:int64 * limit:int64 -> 'T list * int64
  val execute : config:IDbConfig -> connection:DbConnection -> sql:string -> condition:(string * obj * Type) list ->  int
  val executeReader<'T> : config:IDbConfig -> connection:DbConnection -> handler:(DbDataReader -> 'T) -> sql:string -> condition:(string * obj * Type) list -> 'T
  val find<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> idList:obj list -> 'T
  val tryFind<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> idList:obj list -> 'T option
  val findWithVersion<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> idList:obj list -> version:obj -> 'T
  val tryFindWithVersion<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> idList:obj list -> version:obj -> 'T option
  val insert<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> entity:'T -> 'T
  val update<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> entity:'T -> 'T
  val updateWithoutVersion<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> entity:'T -> 'T
  val delete<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> entity:'T -> unit
  val deleteWithoutVersion<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> entity:'T -> unit
  val call<'T when 'T : not struct> : config:IDbConfig -> connection:DbConnection -> procedure:'T -> 'T
  val createConnection : config:IDbConfig -> DbConnection


Soma.Core.LocalDbモジュールは、Soma.Core.Dbモジュールと比較して次の点が異なっています。
  • createConnection関数を持ちます。
  • createConnection関数以外のすべての関数の第二パラメータは System.Data.Common.DbConnection です。

これらの点を除けば、各関数の仕様はSoma.Core.Dbモジュールの同名の関数と同等です。したがって、各関数の仕様はSoma.Core.Dbクラスの同名の関数の説明を参照してください。

Soma.Core.LocalDbモジュールの典型的な使い方を以下に示します。

典型的な利用例
  use tx = new TransactionScope()
  use con = LocalDb.createConnection config

  let emp = LocalDb.find<Employee> config con [1]
  let emp = LocalDb.update config con { emp with EmployeeName = "Hoge" }
  LocalDb.delete config con emp

  tx.Complete()


この例のポイントを説明します。
  • トランザクションは System.Transactions.TransactionScopeクラスを用いて制御します。
  • Soma.Core.LocalDbモジュールの第一引数は 設定 のインスタンスです。毎回第一引数に指定するのは煩雑なので関数の部分適用をしておくとよいでしょう。
  • コネクションは Soma.Core.LocalDb の createConnection関数により生成します。
  • 取得したコネクションは、Soma.Core.LocalDbモジュールの他の関数の呼び出しに使用します。
  • ひとつのトランザクションにはひとつのコネクションのみを関連付けるようにします。

Db.query

SELECTのSQLを指定して複数件をlist<'T>で取得します。
queryのジェネリックパラメータには基本型、レコード型、タプル型、Soma.Core.dynamic型のいずれかを指定できます。ここに指定された型が戻り値のlistの要素の型になります。
タプル型の要素は基本型もしくはレコード型でなければいけません。タプル型の要素に基本型とレコード型が混在する場合は、基本型がレコード型より前に宣言されなければいけません。
第一引数はDBの設定、第二引数はSQL、第三引数は問い合わせ条件です。

さまざまなジェネリックパラメータを用いた例を以下に示します。

例 : ジェネリックパラメータが基本型
let empList = 
  Db.query<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがレコード型
let empList = 
  Db.query<Employee>
    config
    "select * from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型
let empList = 
  Db.query<string, decimal>
    config
    "select EmployeeName, Salary from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素がレコード型
let deptEmpList = 
  Db.query<Department, Employee>
    config
    "select d.*, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型とレコード型の混在
let empList = 
  Db.query<string, Employee>
    config
    "select d.DepartmentName, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがdynamic型
let empList = 
  Db.query<dynamic>
    config
    "select EmployeeId, EmployeeName from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 
empList |> Seq.iter (fun emp -> printfn "%O, %O" emp?EmployeeId emp?EmployeeName)

Db.queryOnDemand

SELECTのSQLを指定して複数件をseq<'T>で取得します。SQLは、戻り値のシーケンスが評価されるまでは実行されません。
queryOnDemandのジェネリックパラメータには基本型、レコード型、タプル型、Soma.Core.dynamic型のいずれかを指定できます。ここに指定された型が戻り値のseqの要素の型になります。
タプル型の要素は基本型もしくはレコード型でなければいけません。タプル型の要素に基本型とレコード型が混在する場合は、基本型がレコード型より前に宣言されなければいけません。
第一引数はDBの設定、第二引数はSQL、第三引数は問い合わせ条件です。

さまざまなジェネリックパラメータを用いた例を以下に示します。

例 : ジェネリックパラメータが基本型
let empSeq = 
  Db.queryOnDemand<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがレコード型
let empSeq = 
  Db.queryOnDemand<Employee>
    config
    "select * from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型
let empSeq = 
  Db.queryOnDemand<string, decimal>
    config
    "select EmployeeName, Salary from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素がレコード型
let deptEmpSeq = 
  Db.queryOnDemand<Department, Employee>
    config
    "select d.*, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型とレコード型の混在
let empSeq = 
  Db.queryOnDemand<string, Employee>
    config
    "select d.DepartmentName, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0"
    ["salary" @= 1000M] 

例 : ジェネリックパラメータがdynamic型
let empSeq = 
  Db.queryOnDemand<dynamic>
    config
    "select EmployeeId, EmployeeName from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 
empSeq |> Seq.iter (fun emp -> printfn "%O, %O" emp?EmployeeId emp?EmployeeName)

Db.pagenate

SELECTのSQLを指定して複数件をlist<'T>で取得します。指定したSQLはページング用のSQLに変換されて実行されます。使用するDBの設定によっては元のSQLに order by 句が指定されている必要があります。
pagenateのジェネリックパラメータには基本型、レコード型、タプル型、Soma.Core.dynamic型のいずれかを指定できます。ここに指定された型が戻り値のlistの要素の型になります。
タプル型の要素は基本型もしくはレコード型でなければいけません。タプル型の要素に基本型とレコード型が混在する場合は、基本型がレコード型より前に宣言されなければいけません。
第一引数はDBの設定、第二引数はSQL、第三引数は問い合わせ条件、第四引数はページングのoffsetとlimitのタプルです。

SQLの変換例を示します。

F# code
let empList = 
  Db.pagenate<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)
変換され実行されるSQL
select 
  * 
from 
  ( select 
      temp_.*, 
      row_number() over( order by Salary) as soma_rownumber_ 
    from 
      ( select EmployeeName from Employee where Salary > @p0 ) as temp_ 
  ) as temp2_ 
where 
  soma_rownumber_ > @p1
  and 
  soma_rownumber_ <= @p2
パラメータ@p0、@p1、@p2 にはそれぞれ 1000M、10、60 がバインドされます。

さまざまなジェネリックパラメータを用いた例を以下に示します。

例 : ジェネリックパラメータが基本型
let empList = 
  Db.pagenate<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがレコード型
let empList = 
  Db.pagenate<Employee>
    config
    "select * from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型
let empList = 
  Db.pagenate<string, decimal>
    config
    "select EmployeeName, Salary from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素がレコード型
let deptEmpList = 
  Db.pagenate<Department, Employee>
    config
    "select d.*, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0 order by e.Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型とレコード型の混在
let empList = 
  Db.pagenate<string, Employee>
    config
    "select d.DepartmentName, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0 order by e.Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがdynamic型
let empList = 
  Db.pagenate<dynamic>
    config
    "select EmployeeId, EmployeeName from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 
    (10L, 50L)
empList |> Seq.iter (fun emp -> printfn "%O, %O" emp?EmployeeId emp?EmployeeName)

Db.pagenateOnDemand

SELECTのSQLを指定して複数件をseq<'T>で取得します。SQLは、戻り値のシーケンスが評価されるまでは実行されません。指定したSQLはページング用のSQLに変換されて実行されます。使用するDBの設定によっては元のSQLに order by 句が指定されている必要があります。
pagenateOnDemandのジェネリックパラメータには基本型、レコード型、タプル型、Soma.Core.dynamic型のいずれかを指定できます。ここに指定された型が戻り値のseqの要素の型になります。
タプル型の要素は基本型もしくはレコード型でなければいけません。タプル型の要素に基本型とレコード型が混在する場合は、基本型がレコード型より前に宣言されなければいけません。
第一引数はDBの設定、第二引数はSQL、第三引数は問い合わせ条件、第四引数はページングのoffsetとlimitのタプルです。

SQLの変換例を示します。

F# code
let empSeq = 
  Db.pagenateOnDemand<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)
変換され実行されるSQL
select 
  * 
from 
  ( select 
      temp_.*, 
      row_number() over( order by Salary) as soma_rownumber_ 
    from 
      ( select EmployeeName from Employee where Salary > @p0 ) as temp_ 
  ) as temp2_ 
where 
  soma_rownumber_ > @p1
  and 
  soma_rownumber_ <= @p2
パラメータ@p0、@p1、@p2 にはそれぞれ 1000M、10、60 がバインドされます。

さまざまなジェネリックパラメータを用いた例を以下に示します。

例 : ジェネリックパラメータが基本型
let empSeq = 
  Db.pagenateOnDemand<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがレコード型
let empSeq = 
  Db.pagenateOnDemand<Employee>
    config
    "select * from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型
let empSeq = 
  Db.pagenateOnDemand<string, decimal>
    config
    "select EmployeeName, Salary from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素がレコード型
let deptEmpSeq = 
  Db.pagenateOnDemand<Department, Employee>
    config
    "select d.*, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型とレコード型の混在
let empSeq = 
  Db.pagenateOnDemand<string, Employee>
    config
    "select d.DepartmentName, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがdynamic型
let empSeq = 
  Db.pagenateOnDemand<dynamic>
    config
    "select EmployeeId, EmployeeName from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 
    (10L, 50L)
empSeq |> Seq.iter (fun emp -> printfn "%O, %O" emp?EmployeeId emp?EmployeeName)

Db.paginateAndCount

指定したSELECTのSQLをページング用のSQLに変換し実行した結果をlist<'T>で取得するとともに、ページング用に変換しないSQLで取得できる件数を同時に取得します。つまり、list<'T> と int64 を要素とするタプルを返します。使用するDBの設定によっては元のSQLに order by 句が指定されている必要があります。
paginateAndCountのジェネリックパラメータには基本型、レコード型、タプル型、Soma.Core.dynamic型のいずれかを指定できます。ここに指定された型が戻り値のlistの要素の型になります。
タプル型の要素は基本型もしくはレコード型でなければいけません。タプル型の要素に基本型とレコード型が混在する場合は、基本型がレコード型より前に宣言されなければいけません。
第一引数はDBの設定、第二引数はSQL、第三引数は問い合わせ条件、第四引数はページングのoffsetとlimitのタプルです。

SQLの変換例を示します。SQLは2つに分かれて実行されます。

F# code
let empList, count = 
  Db.paginateAndCount<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)
変換され実行されるSQL 1
select 
  * 
from 
  ( select 
      temp_.*, 
      row_number() over( order by Salary) as soma_rownumber_ 
    from 
      ( select EmployeeName from Employee where Salary > @p0 ) as temp_ 
  ) as temp2_ 
where 
  soma_rownumber_ > @p1
  and 
  soma_rownumber_ <= @p2
パラメータ@p0、@p1、@p2 にはそれぞれ 1000M、10、60 がバインドされます。

変換され実行されるSQL 2
select 
  count(*) 
from 
  ( select EmployeeName from Employee where Salary > @p0 ) as t_
パラメータ @p0 には1000M がバインドされます。


さまざまなジェネリックパラメータを用いた例を以下に示します。

例 : ジェネリックパラメータが基本型
let empList, count = 
  Db.paginateAndCount<string>
    config
    "select EmployeeName from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがレコード型
let empList, count = 
  Db.paginateAndCount<Employee>
    config
    "select * from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型
let empList, count = 
  Db.paginateAndCount<string, decimal>
    config
    "select EmployeeName, Salary from Employee where Salary > /* salary */0 order by Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素がレコード型
let deptEmpList, count = 
  Db.paginateAndCount<Department, Employee>
    config
    "select d.*, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0 order by e.Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがタプル型 かつ タプル型の要素が基本型とレコード型の混在
let empList, count = 
  Db.paginateAndCount<string, Employee>
    config
    "select d.DepartmentName, e.* from Employee e inner join Department d on (e.DepartmentId = d.DepartmentId) where e.Salary > /* salary */0 order by e.Salary"
    ["salary" @= 1000M] 
    (10L, 50L)

例 : ジェネリックパラメータがdynamic型
let empList, count = 
  Db.paginateAndCount<dynamic>
    config
    "select EmployeeId, EmployeeName from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 
    (10L, 50L)
empList |> Seq.iter (fun emp -> printfn "%O, %O" emp?EmployeeId emp?EmployeeName)

Db.execute

任意のSQLを指定して結果件数を取得します。

例 : 複数件の削除
let rows = 
  Db.execute
    config
    "delete from Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

Db.executeReader

SQLの結果セットをハンドリングします。

例 : データテーブルへのロード
let table = 
  Db.executeReader<DataTable>
    config
    (fun reader ->
      let table = new DataTable()
      table.Load reader
      table )
    "select from * Employee where Salary > /* salary */0"
    ["salary" @= 1000M] 

Db.find

主キーで一件を検索し、結果をレコード型のインスタンスで取得します。
findのジェネリックパラメータにはレコード型を指定できます。ここに指定された型が戻り値の型になります。
ジェネリックパラメータに指定するレコード型のフィールドにはIdAttributeが適切に付与されている必要があります。
findの第一引数には主キーのリストを渡します。

典型的な検索処理の例を以下に示します。

例 :典型的な検索処理
let emp = Db.find<Employee> config [1]

結果が見つからない場合は EntityNotFoundException をスローします。
EntityNotFoundException を処理する例を以下に示します。

例 : EntityNotFoundException を処理する
try
  let emp = Db.find<Employee> config [1]
  ...
with
| EntityNotFoundException  _ -> 
  ...

Db.tryFind

主キーで一件を検索し、結果をレコード型を要素とするオプション型のインスタンスで取得します。戻り値は、結果があれば Some、結果がなければ None になります。
tryFindのジェネリックパラメータにはレコード型を指定できます。ここに指定された型が戻り値のオプション型の要素の型になります。
ジェネリックパラメータに指定するレコード型のフィールドにはIdAttributeが適切に付与されている必要があります。
tryFindの第一引数には主キーのリストを渡します。

典型的な検索処理の例を以下に示します。

例 : 典型的な検索処理
let emp = Db.tryFind<Employee> config [1]

Db.findWithVersion

主キーで一件を検索し、バージョンをチェックしてから結果をレコード型のインスタンスで取得します。
findWithVersionのジェネリックパラメータにはレコード型を指定できます。ここに指定された型が戻り値の型になります。
ジェネリックパラメータに指定するレコード型のフィールドにはIdAttributeとVersionAttributeが適切に付与されている必要があります。
findWithVersionの第一引数には主キーのリストを、第二引数にはバージョンを渡します。

典型的な検索処理の例を以下に示します。

例 :典型的な検索処理
let emp = Db.findWithVersion<Employee> config [1] 0

主キーによる検索で結果が見つからない場合は EntityNotFoundException をスローします。
EntityNotFoundException を処理する例を以下に示します。

例 : EntityNotFoundException を処理する
try
  let emp = Db.findWithVersion<Employee> config [1] 0
  ...
with
| EntityNotFoundException  _ -> 
  ...

主キーによる検索で結果が見つかってもバージョンが異なる場合は OptimisticLockException をスローします。
OptimisticLockException を処理する例を以下に示します。

例 : OptimisticLockException を処理する
try
  let emp = Db.findWithVersion<Employee> config [1] 99
  ...
with
| OptimisticLockException _ -> 
  ...

Db.tryFindWithVersion

主キーで一件を検索し、バージョンをチェックしてから結果をレコード型を要素とするオプション型のインスタンスで取得します。戻り値は、結果があれば Some、結果がなければ None になります。
tryFindWithVersionのジェネリックパラメータにはレコード型を指定できます。ここに指定された型が戻り値のオプション型の要素の型になります。
ジェネリックパラメータに指定するレコード型のフィールドにはIdAttributeとVersionAttributeが適切に付与されている必要があります。
tryFindWithVersionの第一引数には主キーのリストを、、第二引数にはバージョンを渡します。

典型的な検索処理の例を以下に示します。

例 : 典型的な検索処理
let emp = Db.tryFindWithVersion<Employee> config [1] 0

主キーによる検索で結果が見つかってもバージョンが異なる場合は OptimisticLockException をスローします。
OptimisticLockException を処理する例を以下に示します。

例 : OptimisticLockException を処理する
try
  let emp = Db.tryFindWithVersion<Employee> config [1] 99
  ...
with
| OptimisticLockException _ -> 
  ...

Db.insert

レコードに対応する行を挿入します。戻り値では新しいレコードを返しますが、IdAttributeやVersionAttributeの設定に基づきフィールドの値を更新して返します。
ジェネリックパラメータにはレコード型を指定できます。
一意制約違反が発生した場合、UniqueConstraintExceptionをスローします。

典型的な挿入処理の例を以下に示します。

例 : 典型的な挿入処理
let emp = { EmployeeId = 0; EmployeeName = "Hoge"; VersionNo = 0 }
let emp = Db.insert<Employee> config emp

UniqueConstraintExceptionを処理する例を示します。

例 : UniqueConstraintExceptionを処理
let emp = { EmployeeId = 0; EmployeeName = "Hoge"; VersionNo = 0 }
try
  let emp = Db.insert<Employee> config emp
  ...
with 
| UniqueConstraintException _ ->
  ...

Db.insertWithOpt

オプションを指定してレコードに対応する行を挿入します。オプションを利用すると次のことが可能になります。
  • INSERT INTO 句から特定のフィールド(にマッピングされたカラム)を除外する
  • INSERT INTO 句に特定のフィールド(にマッピングされたカラム)のみを含める
  • INSERT INTO 句から値がNULLであるフィールド(にマッピングされたカラム)を除外する

挿入処理のオプションは Soma.Core.InsertOpt クラスで表します。
オプション以外に関する仕様は、前述の Db.insert 関数と同様です。

INSERT INTO 句から特定のフィールド(にマッピングされたカラム)を除外するには、 InsertOptクラスのExcludeプロパティに除外したいフィールド名を指定します。
指定するのはカラム名ではなく、カラム名にマッピングされたフィールド名であることに注意してください。
以下に例を示します。

例 : INSERT INTO 句から特定のフィールドを除外する
let emp = { EmployeeId = 0; EmployeeName = "Hoge"; Age = Some 21; Salary = Some 200000M; VersionNo = 0 }
let emp = Db.insertWithOpt<Employee> config emp (InsertOpt(Exclude = ["Age"; "Salary"]))

INSERT INTO 句に特定のフィールド(にマッピングされたカラム)のみを含めるには、 InsertOptクラスのIncludeプロパティに含めたいフィールド名を指定します。
指定するのはカラム名ではなく、カラム名にマッピングされたフィールド名であることに注意してください。
以下に例を示します。

例 : INSERT INTO 句に特定のフィールドのみを含める
let emp = { EmployeeId = 0; EmployeeName = "Hoge"; Age = Some 21; Salary = Some 200000M; VersionNo = 0 }
let emp = Db.insertWithOpt<Employee> config emp (InsertOpt(Include = ["EmployeeName"]))

INSERT INTO 句から値がNULLであるフィールド(にマッピングされたカラム)を除外するには、InsertOptクラスのExcludeNullプロパティをtrueに設定します。
以下に例を示します。

例 : INSERT INTO 句から値がNULLであるフィールドを除外する
let emp = { EmployeeId = 0; EmployeeName = "Hoge"; Age = None; Salary = None; VersionNo = 0 }
let emp = Db.insertWithOpt<Employee> config emp (InsertOpt(ExcludeNull= true))

Db.update

レコードに対応する行を更新します。戻り値では新しいレコードを返しますが、VersionAttributeの設定に基づきフィールドの値を更新して返します。
ジェネリックパラメータにはレコード型を指定できます。
レコード型は主キーカラムに対応するフィールドを持っている必要があります。主キーカラムに対応するフィールドはIdAttributeで指定します。
レコード型がバージョンカラムに対応するフィールドを持つ場合、楽観的排他制御を行います。すなわち、更新件数が0件の場合OptimisticLockExceptionをスローします。バージョンカラムに対応するフィールドはVersionAttributeで指定します。
一意制約違反が発生した場合、UniqueConstraintExceptionをスローします。

典型的な更新処理の例を以下に示します。

例 : 典型的な更新処理
let emp = Db.find<Employee> config [1]
let emp = Db.update<Employee> config { emp with EmployeeName = "Hoge" }

UniqueConstraintExceptionを処理する例を示します。

例 : UniqueConstraintExceptionを処理
let emp = Db.find<Employee> config [1]
try
  let emp = Db.update<Employee> config { emp with EmployeeName = "Hoge" }
  ...
with 
| UniqueConstraintException _ ->
  ...

OptimisticLockExceptionを処理する例を示します。

例 : OptimisticLockExceptionを処理
let emp = Db.find<Employee> config [1]
try
  let emp = Db.update<Employee> config { emp with EmployeeName = "Hoge" }
  ...
with 
| OptimisticLockException _ ->
  ...

レコード型がバージョンカラムに対応するフィールドを持たない場合で更新件数が0件の場合、NoAffectedRowExceptionをスローします。
NoAffectedRowExceptionを処理する例を以下に示します。

例 : NoAffectedRowExceptionを処理
let emp = Db.find<Employee> config [1]
try
  let emp = Db.update<Employee> config { emp with EmployeeName = "Hoge" }
  ...
with 
| NoAffectedRowException _ ->
  ...

Db.updateWithOpt

オプションを指定してレコードに対応する行を更新します。オプションを利用すると次のことが可能になります。
  • SET 句から特定のフィールド(にマッピングされたカラム)を除外する
  • SET 句に特定のフィールド(にマッピングされたカラム)のみを含める
  • SET 句から値がNULLであるフィールド(にマッピングされたカラム)を除外する
  • バージョンを無視する

更新処理のオプションは Soma.Core.UpdateOpt クラスで表します。
オプション以外に関する仕様は、前述の Db.update 関数と同様です。

SET 句から特定のフィールド(にマッピングされたカラム)を除外するには、 UpdateOptクラスのExcludeプロパティに除外したいフィールド名を指定します。
指定するのはカラム名ではなく、カラム名にマッピングされたフィールド名であることに注意してください。
以下に例を示します。

例 : SET 句から特定のフィールドを除外する
let emp = { EmployeeId = 1; EmployeeName = "Hoge"; Age = Some 21; Salary = Some 200000M; VersionNo = 1 }
let emp = Db.updateWithOpt<Employee> config emp (UpdateOpt(Exclude = ["Age"; "Salary"]))

SET 句に特定のフィールド(にマッピングされたカラム)のみを含めるには、 UpdateOptクラスのIncludeプロパティに除外したいフィールド名を指定します。
指定するのはカラム名ではなく、カラム名にマッピングされたフィールド名であることに注意してください。
以下に例を示します。

例 : SET 句に特定のフィールドのみを含める
let emp = { EmployeeId = 1; EmployeeName = "Hoge"; Age = Some 21; Salary = Some 200000M; VersionNo = 1 }
let emp = Db.updateWithOpt<Employee> config emp (UpdateOpt(Include = ["EmployeeName"]))

SET 句から値がNULLであるフィールド(にマッピングされたカラム)を除外するには、UpdateOptクラスのExcludeNullプロパティをtrueに設定します。
以下に例を示します。

例 : SET 句から値がNULLであるフィールドを除外する
let emp = { EmployeeId = 1; EmployeeName = "Hoge"; Age = None; Salary = None; VersionNo = 1 }
let emp = Db.updateWithOpt<Employee> config emp (UpdateOpt(ExcludeNull= true))

バージョンを無視するには、UpdateOptクラスのIgnoreVersionプロパティをtrueに設定します。
バージョンを無視するとバージョンフィールドにマッピングされたカラムがSET 句と WHERE 句の両方から除外され、OptimisticLockException が発生しなくなります。
以下に例を示します。

例 : バージョンを無視する
let emp = { EmployeeId = 1; EmployeeName = "Hoge"; Age = None; Salary = None; VersionNo = 1 }
let emp = Db.updateWithOpt<Employee> config emp (UpdateOpt(IgnoreVersion= true))

Db.delete

レコードに対応する行を削除します。
ジェネリックパラメータにはレコード型を指定できます。
レコード型は主キーカラムに対応するフィールドを持っている必要があります。主キーカラムに対応するフィールドはIdAttributeで指定します。
レコード型がバージョンカラムに対応するフィールドを持つ場合、楽観的排他制御を行います。すなわち、削除件数が0件の場合OptimisticLockExceptionをスローします。バージョンカラムに対応するフィールドはVersionAttributeで指定します。

典型的な削除処理の例を以下に示します。

例 : 典型的な削除処理
let emp = Db.find<Employee> config [1]
Db.delete<Employee> config emp

OptimisticLockExceptionを処理する例を示します。

例 : OptimisticLockExceptionを処理
let emp = Db.find<Employee> config [1]
try
  Db.delete<Employee> config emp
  ...
with 
| OptimisticLockException _ ->
  ...

レコード型がバージョンカラムに対応するフィールドを持たない場合で削除件数が0件の場合、NoAffectedRowExceptionをスローします。
NoAffectedRowExceptionを処理する例を以下に示します。

例 : NoAffectedRowExceptionを処理
let emp = Db.find<Employee> config [1]
try
  Db.delete<Employee> config emp
  ...
with 
| NoAffectedRowException _ ->
  ...

Db.deleteWithOpt

オプションを指定してレコードに対応する行を削除します。オプションを利用すると次のことが可能になります。
  • バージョンを無視する

削除処理のオプションは Soma.Core.DeleteOpt クラスで表します。
オプション以外に関する仕様は、前述の Db.delete 関数と同様です。

バージョンを無視するには、DeleteOptクラスのIgnoreVersionプロパティをtrueに設定します。
バージョンを無視するとバージョンフィールドにマッピングされたカラムが WHERE 句から除外され、OptimisticLockException が発生しなくなります。
以下に例を示します。

例 : バージョンを無視する
let emp = Db.find<Employee> config [1]
Db.deleteWithOpt<Employee> config emp (DeleteOpt(IgnoreVersion= true))

Db.call

ストアドプロシージャを実行します。
一意制約違反が発生した場合、UniqueConstraintExceptionをスローします。
ストアドプロシージャとレコードのマッピング方法については マッピング を参照してください。

典型的なストアドプロシージャ呼び出しを以下に示します。

例 : 典型的なストアドプロシージャ呼び出し
let procedure = { Param1 = 1; Param2= 2; Param3 = 0 }
let procedure = Db.call<ProcMultiParams> config procedure

UniqueConstraintExceptionを処理する例を示します。

例 : UniqueConstraintExceptionを処理
let procedure = { Param1 = 1; Param2= 2; Param3 = 0 }
try
  let procedure = Db.call<ProcMultiParams> config procedure
  ...
with 
| UniqueConstraintException _ ->
  ...

Last edited Aug 21, 2011 at 2:05 AM by toshihiro, version 29

Comments

No comments yet.