かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

F# 2.0でEntity Framework 4.1 CodeFirst

とりあえず備忘録です。さくっとやって動かなかったので、ぐぐって以下のページを見つけてその通りにやったら動きました。今の所CodeFirstでやるなら大人しくC#使っておいた方がいいのかな・・・?といった所感です。

namespace SampleApplication

    open System
    open System.ComponentModel.DataAnnotations
    open System.Data.Entity
    open System.Data.Objects.DataClasses

    // クラスは名前空間に所属させる
    type Employee() =

        let mutable id = 0
        let mutable name = ""

        member x.ID
            with get() = id
            and set v = id <- v

        member x.Name
            with get() = name
            and set v = name <- v

    type EduContext() =
        inherit DbContext()

        // valとDefaultValueを使って未初期化でもOKなように細工
        [<DefaultValue>]
        val mutable employee : IDbSet<Employee>

        member public x.Employees
            with get() = x.employee 
            and set v = x.employee <- v

    module Test = 
        [<EntryPoint>]
        let main(_) =
            Database.SetInitializer(
                DropCreateDatabaseIfModelChanges<EduContext>())

            // あとは普通に使える
            use ctx = new EduContext()
            // 追加
            ctx.Employees.Add(Employee(Name = "田中 太郎")) |> ignore
            let updateCount = ctx.SaveChanges()
            printfn "%d" updateCount

            // 再読み込み
            ctx.Employees.Load()
            // 取得データの表示
            ctx.Employees
                |> Seq.iter (fun e -> printfn "%d %s" e.ID e.Name)

            0

App.configには以下のように接続文字列を追加しました。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>
    <connectionStrings>
        <!-- コンテキストのクラス名と同じ名前で接続文字列を作成する -->
        <add name="EduContext"
             connectionString="Data Source=|DataDirectory|SampleDatabase.sdf"
             providerName="System.Data.SqlServerCe.4.0"/>
    </connectionStrings>
</configuration>

ポイントはクラスを名前空間に明示的に所属させることと、IDbSetはvalとDefaultValueAttributeを使って未初期化状態を明示することです。これをしないと実行時に例外が出ちゃいます。