かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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を使って未初期化状態を明示することです。これをしないと実行時に例外が出ちゃいます。