This project is read-only.

目次

概要

データベースのテーブルやストアドプロシージャは、F#のレコード型、もしくはデフォルトコンストラクタを持つ参照型のクラスにマッピングできます。
開発言語にC#やVB.NETを利用する場合は参照型のクラスを利用してください。

テーブルとレコードのマッピング

データベースのテーブルはF#レコードに、テーブルのカラムはレコードのフィールドにマッピングできます。
以下にテーブル定義と対応するレコード型の定義の例を示します。

DDL : Department テーブル
create table Department (
    DepartmentId int identity primary key,
    DepartmentName varchar(50) unique,
    VersionNo int not null
);

F# : Department レコード
open Soma.Core

type Department = 
  { [<Id(IdKind.Identity)>]
    DepartmentId : int 
    DepartmentName : string
    [<Version>]
    VersionNo : int }

また、テーブルはデフォルトコンストラクタを持つ参照型のクラスに、カラムはプロパティにマッピングできます。ただし、カラムにマッピングするプロパティはpublic な getter と setter を両方持つ必要があります。
以下にC#で定義したクラスの例を示します。

C# : Department クラス
using Soma.Core;

public class Department
{
    [Id(IdKind.Identity)]
    public int DepartmentId { get; set; }
    public string DepartmentName { get; set; }
    [Version]
    public int VersionNo { get; set; }
}

テーブル定義

テーブル名は暗黙的にレコード名にマッピングされます。
TableAttributeを付与すると、カタログ名、スキーマ名、テーブル名を明示できます。
カタログ名、スキーマ名、テーブル名には、それぞれ TableAttribute のCatalogプロパティ、Schemaプロパティ、Nameプロパティが対応します。
以下にTableAttributeを利用した例を示します。

例 : TableAttributeの利用
open Soma.Core

[<Table(Catalog = "CATALOG", Schema = "SCHEMA", Name = "DEPT")>]
type Department = 
  { ... }

TableAttribute の IsEnclosed プロパティを true に設定すると、カタログ名、スキーマ名、テーブル名のそれぞれがRDBMSがサポートする引用符で囲まれます。これにより、RDBMSで予約された語を識別子として利用できます。
以下にIsEnclosed プロパティを利用した例と生成されるSQLの例を示します。
例 : IsEnclosedの利用
open Soma.Core

[<Table(IsEnclosed = true)>]
type Department = 
  { ... }
例 : IsEnclosedを利用した場合に生成されるSQL
select ... from [Department]

カラム定義

カラム名は暗黙的にレコードのフィールド名にマッピングされます。
カラム名を明示するにはフィールドにColumnAttributeを付与し、ColumnAttributeのNameプロパティにカラム名を設定します。
以下にColumnAttributeを利用した例を示します。

例 : ColumnAttributeのNameプロパティの利用
open Soma.Core

type Department = 
  { ...
    [<Column(Name = "DEPTNAME")>]
    DepartmentName : string }

ColumnAttribute は、Nameプロパティの他に Insertable プロパティと Updatable プロパティを持ちます。これらのプロパティに false を設定すると、それぞれINSERTやUPDATEの対象外になります。
以下にUpdatableプロパティを利用した例を示します。

例 : ColumnAttributeのUpdatableプロパティの利用
open Soma.Core

type Department = 
  { ...
    [<Column(Updatable= false)>]
    DepartmentName : string }

ColumnAttribute の IsEnclosed プロパティを true に設定すると、カラム名がRDBMSがサポートする引用符で囲まれます。これにより、RDBMSで予約された語を識別子として利用できます。
以下にIsEnclosed プロパティを利用した例と生成されるSQLの例を示します。
例 : IsEnclosedの利用
open Soma.Core

type Department = 
  { ...
    [<Column(IsEnclosed= true)>]
    DepartmentName : string }
例 : IsEnclosedを利用した場合に生成されるSQL
select ... [DepartmentName] ... from Department

主キー

主キーカラムに対応するレコードのフィールドにはIdAttributeを付与します。
単にIdAttributeを付与した場合、IdAttributeのコンストラクタにはIdKind.Assignedを指定したのと同じ意味になります。IdKind.Assignedは、主キーの値の設定をアプリケーションで行うことを意味します。
以下に、IdAttributeを利用した例を示します。

例 : IdAttributeの利用
open Soma.Core

type Department = 
  { [<Id>]
    DepartmentId : int 
    ... }

主キーカラムに対し自動インクリメントをする定義をしている場合は、IdAttributeのコンストラクタにIdKind.Identityを指定します。IdKind.Identityを指定すると、データベースで採番された値がレコードのフィールドに自動で設定されます。
この機能が使えるRDBMSは以下の通りです。
  • Microsoft SQL Server 2008
  • Microsoft SQL Server Compact 4.0
  • MySQL 5.x
  • SQLite 3
以下に、IdKind.Identityを利用した例を示します。

例 : IdAttributeとIdKind.Identityの利用
open Soma.Core

type Department = 
  { [<Id(IdKind.Identity)>]
    DepartmentId : int 
    ... }

主キーカラムにシーケンスの値を自動で設定したい場合は、IdAttributeのコンストラクタにIdKind.Sequenceを指定し、さらにSequenceAttributeを指定します。
この機能が使えるRDBMSはOracle Database 11g のみです。
SequenceAttribute の Name プロパティには、シーケンスの名前を指定します。指定しない場合は、テーブル名_SEQ となります。
SequenceAttribute の IncrementBy プロパティはシーケンスの増分値を指定します。デフォルトは1です。シーケンス定義の増分値とこのプロパティに指定する値は合わせてください。このプロパティを1より大きくするとDBアクセスの回数が減りパフォーマンスが向上します。
以下に、IdKind.Sequenceを利用した例を示します。

例 : IdAttributeとIdKind.Sequenceの利用
open Soma.Core

type Department = 
  { [<Id(IdKind.Sequence)>]
    [<Sequence>]
    DepartmentId : int 
    ... }

バージョン

バージョンカラムに対応するレコードのフィールドにはVersionAttributeを付与します。
単にVersionAttributeを付与した場合、VersionAttributeのコンストラクタにはVersionKind.Incrementedを指定したのと同じ意味になります。VersionKind.Incrementedは、数値型のフィールドの値を自動で増分します。
以下に、VersionAttributeを利用した例を示します。

例 : VersionAttributeの利用
open Soma.Core

type Department = 
  { [<Version>]
    VersionNo : int 
    ... }

データベースで生成されたバージョン値を自動で設定したい場合は、VersionAttribute のコンストラクタに VersionKind.Computed を指定し、フィールドの型をbyte[]にします。
この機能が使えるRDBMSは以下の通りです。
  • Microsoft SQL Server 2008
  • Microsoft SQL Server Compact 4.0
フィールドに対応するカラムのデータ型はrowversion 型もしくは timestamp 型でなければいけません。
以下に、VersionAttribute と VersionKind.Computed を利用した例を示します。

例 : VersionAttribute と VersionKind.Computed の利用
open Soma.Core

type Department = 
  { [<Version(VersionKind.Computed)>]
    VersionNo : byte[] 
    ... }

ストアドプロシージャとレコードのマッピング

データベースのストアドプロシージャはレコードに、ストアドプロシージャへのパラメータはレコードのフィールドにマッピングできます。
なお、ストアドプロシージャという用語はストアドファンクションも含めるものとします。
以下にストアドプロシージャ定義と対応するレコード型の定義の例を示します。

DDL : ProcMultiParams ストアドプロシージャ
CREATE PROCEDURE [dbo].[ProcMultiParams]
    @Param1 int,
    @Param2 int OUTPUT,
    @Param3 int OUTPUT
AS
BEGIN
    SET @Param2 = @Param2 + @Param1;
    SET @Param3 = @Param1;
END

F# : ProcMultiParams レコード
open Soma.Core

type ProcMultiParams =
  { Param1 : int
    [<ProcedureParam(Direction = Direction.InputOutput)>]
    Param2 : int
    [<ProcedureParam(Direction = Direction.Output)>]
    Param3 : int }

また、ストアドプロシージャーはデフォルトコンストラクタを持つ参照型のクラスに、パラメータはプロパティにマッピングできます。ただし、パラメータにマッピングするプロパティはpublic な getter と setter を両方持つ必要があります。
以下にC#で定義したクラスの例を示します。

C# : ProcMultiParams クラス
using Soma.Core;

public class ProcMultiParams
{
    public int Param1 { get; set; }
    [ProcedureParam(Direction = Direction.InputOutput)]
    public int Param2 { get; set; }
    [<ProcedureParam(Direction = Direction.Output)>]
    public int Param3 { get; set; }
}

ストアドプロシージャ定義

プロシージャ名は暗黙的にレコード名にマッピングされます。
ProcedureAttributeを付与すると、カタログ名、スキーマ名、プロシージャ名を明示できます。
カタログ名、スキーマ名、プロシージャ名には、それぞれ ProcedureAttribute のCatalogプロパティ、Schemaプロパティ、Nameプロパティが対応します。
以下にProcedureAttributeを利用した例を示します。

例 : ProcedureAttribute の利用
open Soma.Core

[<Procedure(Catalog = "CATALOG", Schema = "SCHEMA", Name = "PROC")>]
type ProcMultiParams = 
  { ... }

ProcedureAttribute の IsEnclosed プロパティを true に設定すると、カタログ名、スキーマ名、テーブル名のそれぞれがRDBMSがサポートする引用符で囲まれます。これにより、RDBMSで予約された語を識別子として利用できます。
以下にIsEnclosed プロパティを利用した例を示します。
例 : IsEnclosedの利用
open Soma.Core

[<Procedure(IsEnclosed = true)>]
type ProcMultiParams = 
  { ... }

ストアドプロシージャのパラメータ定義

パラメータ名は暗黙的にレコードのフィールド名にマッピングされます。
パラメータ名を明示するにはフィールドにProcedureParamAttributeを付与し、ProcedureParamAttributeのNameプロパティにパラメータ名を設定します。
以下にProcedureParamAttributeを利用した例を示します。

例 : ProcedureParamAttribute の Name プロパティの利用
open Soma.Core

type ProcMultiParams = 
  { [<ProcedureParam(Name = "P1")>]
    Param1: int 
    ... }

パラメータの方向

パラメータには、ProcedureParamAttribute の Direction プロパティで方向を示せます。
方向には次の5つがあります。

方向 説明
Input 入力パラメータを表します。指定しない場合のデフォルト値です。
InputOutput 入出力のどちらにも利用されるパラメータを表します。
Output 出力パラメータを表します。
ReturnValue ストアドプロシージャの戻り値を表します。
Result SELECT文で取得できる結果セットを表します。この値が指定されたプロパティの型は、F#のlistもしくはSystem.Collections.Generics.IListと互換性を持つ型でなければいけません。F#のlistもしくはSystem.Collections.Generics.IListと互換性を持つ型の要素の型は、 基本型、レコード型、基本型もしくはレコード型を要素とするタプル型のいずれかでなけれいけません。

以下にProcedureParamAttribute の Direction プロパティの使用例を示します。

例 : ProcedureParamAttribute の Direction プロパティの利用
open Soma.Core

type Employee =
  { EmployeeId : int
    EmployeeName : string }

type ProcDirections = 
  { [<ProcedureParam(Direction = Direction.Input)>]
    Param1: int 
    [<ProcedureParam(Direction = Direction.InputOutput)>]
    Param2: int 
    [<ProcedureParam(Direction = Direction.Output)>]
    Param3: int 
    [<ProcedureParam(Direction = Direction.ReturnValue)>]
    Param4: int 
    [<ProcedureParam(Direction = Direction.Result)>]
    Param5: int list
    [<ProcedureParam(Direction = Direction.Result)>]
    Param6: Employee list }

パラメータの順番

パラメータの順番は、レコードに定義された順番となります。パラメータの位置はストアドプロシージャの定義に合わせてください。
また、パラメータの方向がResultであるパラメータの定義にはRDBMSごとに以下の点に注意してください。

SQL Server もしくはMySQLの場合
Resultパラメータは任意の位置に定義できます。
ただし、複数のResultパラメータが存在する場合は結果が返される順番に合わせて定義してください。

Oracle Databaseの場合
ResultパラメータはカーソルのOUTPUTパラメータとして定義してください。

入出力系パラメータが存在しない場合

Input、InputOutput、Outputのいずれのパラメータも存在しない場合は次のように定義し実行できます。

例 1
type ProcNoneParam = 
  { Unit : unit }

Db.call config { Unit = () }

もしくは、戻り値のパラメータは存在するので、次のように定義し実行できます。

例 2
type ProcNoneParam = 
  { [<ProcedureParam(Direction = Direction.ReturnValue)>]
    Ret : int }

Db.call config { Ret = 0 }

Oracle UDT 型

Oracle の UDT 型 はサポートされています.

例 : UDT 型へのマッピング
type UdtParam = 
  { [<ProcedureParam(UdtTypeName = "MyUdt")>]
    Values : string array }

型のマッピング

レコードのフィールドやクラスのプロパティで利用できる.NET Framework型について説明します。

RDBMSのデータ型と.NET Framework型のマッピング

RDBMSのデータ型と.NET Framework型は、RDBMSごとに以下に示すようにマッピングされます。

Microsoft SQL Server 2008

SQL Serverの型 .NET Framework型 説明
tinyint System.Byte
smallint System.Int16
int System.Int32
bigint System.Int64
binary System.Byte[]
image System.Byte[]
varbinary System.Byte[]
rowversion System.Byte[]
timestamp System.Byte[]
bit System.Boolean
date System.DateTime
datetime System.DateTime
datetime2 System.DateTime
smalldatetime System.DateTime
datetimeoffset System.DateTimeOffset
time System.TimeSpan
decimal System.Decimal
numeric System.Decimal
money System.Decimal
smallmoney System.Decimal
float System.Double
real System.Single
varchar System.String
nvarchar System.String
ntext System.String
uniqueidentifier System.Guid

Microsoft SQL Server Compact 4.0

SQL Server Compactの型 .NET Framework型 説明
tinyint System.Byte
smallint System.Int16
int System.Int32
bigint System.Int64
binary System.Byte[]
image System.Byte[]
varbinary System.Byte[]
rowversion System.Byte[]
timestamp System.Byte[]
bit System.Boolean
datetime System.DateTime
decimal System.Decimal
numeric System.Decimal
money System.Decimal
float System.Double
real System.Single
nvarchar System.String
ntext System.String
uniqueidentifier System.Guid

Oracle Database 11g

Oracle Databaseの型 .NET Framework型 説明
raw System.Byte[]
timestamp System.DateTime
number System.Byte
number System.Int16
number System.Int32
number System.Int64
number System.Decimal
number System.Boolean number型の1がSystem.Booleanのtrueに、1以外の他の値(ただしNULLは除く)がfalseにマッピングされる。
float System.Double
float System.Single
varchar2 System.String
nvarchar2 System.String
interval day to second System.TimeSpan

SQLite 3

SQLiteの型 .NET Framework型 説明
integer System.Byte
integer System.Int16
integer System.Int32
integer System.Int64
numeric System.Decimal
numeric System.Boolean numeric 型の1がSystem.Booleanのtrueに、1以外の他の値(ただしNULLは除く)がfalseにマッピングされる。
real System.Double
real System.Single
text System.String
text System.DateTime
blob System.Byte[]
blob System.Guid

間接的にマッピング可能な.NET Framework型

列挙型、オプション型、null許容型については、基になる型や要素の型により間接的にデータベースのデータ型にマッピングできます。

列挙型

列挙型を利用する場合、基になる型をデータベースのデータ型にマッピングできます。
以下に例を示します。

DDL
create table Person (
  PersonId int identity primary key,
  PersonName varchar(50) not null,
  JobKind int not null,
  VersionNo int not null
)
F#
type JobKind =
  | Salesman = 0
  | Manager = 1

type Person =
  { [<Id(IdKind.Identity)>]
    PersonId : int
    PersonName : string
    JobKind : JobKind
    [<Version>]
    VersionNo : int }

JobKind 列挙型の JobKind フィールドについて説明します。
JobKind 列挙型の基になる型はSystem.Int32です。したがって、JobKind フィールドはSQL Server のint型にマッピングされます。

オプション型

オプション型を利用する場合、要素の型をデータベースのデータ型にマッピングできます。
オプション型を利用すると、データベース上の非NULLをSomeで、またNULLをNoneで表現できます。
以下に例を示します。

DDL
create table Person (
  PersonId int identity primary key,
  PersonName varchar(50),
  JobKind int,
  VersionNo int
)
F#
type JobKind =
  | Salesman = 0
  | Manager = 1

type Person =
  { [<Id(IdKind.Identity)>]
    PersonId : int option
    PersonName : string option
    JobKind : JobKind option
    [<Version>]
    VersionNo : int option }

null 許容型

null 許容型を利用する場合、要素の型をデータベースのデータ型にマッピングできます。
null 許容型を利用すると、データベース上のNULLを表現できる型になります。
以下に例を示します。

DDL
create table Person (
  PersonId int identity primary key,
  PersonName varchar(50),
  JobKind int,
  VersionNo int
)
F#
type JobKind =
  | Salesman = 0
  | Manager = 1

type Person =
  { [<Id(IdKind.Identity)>]
    PersonId : int Nullable
    PersonName : string
    JobKind : JobKind Nullable
    [<Version>]
    VersionNo : int Nullable }

F#を利用する場合は、null許容型よりもオプション型を利用することが推奨されます。null許容型はC#やVB.NETで使用するとよいでしょう。

Last edited Mar 20, 2012 at 4:13 AM by toshihiro, version 38

Comments

No comments yet.