ADO.NET vNextをさわってみる

ADO.NET vNext
ADO.NETの次のバージョンはvNextと呼ぶらしいです。ぱっと見、JavaのPersistence API(JPA)でいうところのJPQL、EntityManager、Entityクラス、Embeddedクラス、継承戦略に相当するものがあって似ているのかなぁという印象です。

明らかにちがうところは、

  • 問い合わせをオブジェクトで行うLINQがある。
  • エンティティがPlain Objectではない(Visual StudioによってSystem.Data.Objects.Entityを継承したクラスが生成される)。
  • 遅延ローディングを行うには明示的にメソッド(EntityRef.Load()とか)を呼び出す必要がある。
  • Update時に明示的にメソッド(ObjectContext.SaveChanges())を呼び出す必要がある(ドキュメントには将来的に不要にするかも、と書いてあるように読める)。
  • アノテーションアトリビュート)でエンティティを定義できない(将来的には対応するらしい。いまはVisual Studio使うとXMLが3つ生成されて細かなところは手で直すといった感じです。)

といったかんじです。


以下、VBで簡単なCRUDのサンプル。

Imports NorthwindCTPModel
Imports System.Transactions

Module Module1

    Sub Main()
        ' eSQLを使って問い合わせ
        SelectWithESQL()

        ' LINQを使って問い合わせ(やってることは上のeSQLを使った問い合わせとまったく同じ)
        SelectWithLINQ()

        ' 追加
        Dim productId As Integer = Insert()

        ' 更新
        Update(productId)

        ' 削除
        Delete(productId)

        Console.ReadLine()
    End Sub


    ' eSQLを使って問い合わせ
    Sub SelectWithESQL()
        Using db As New NorthwindCTP
            Dim q As Query(Of Products) = db.GetQuery(Of Products)( _
                "SELECT VALUE p FROM Products AS p WHERE p.Category.CategoryName = @CategoryName", _
                New QueryParameter("CategoryName", "Beverages"))

            For Each product In q
                ' 遅延ローディング
                product.CategoryRef.Load()

                Console.WriteLine("{0}" & vbTab & "{1}" & vbTab & "{2}", _
                    product.ProductID, product.ProductName, product.Category.CategoryName)
            Next

        End Using
    End Sub

    ' LINQを使って問い合わせ
    Sub SelectWithLINQ()
        Using db As New NorthwindCTP
            Dim q = From p In db.Products _
                Where p.Category.CategoryName = "Beverages" _
                Select p

            For Each product In q
                ' 遅延ローディング
                product.CategoryRef.Load()

                Console.WriteLine("{0}" & vbTab & "{1}" & vbTab & "{2}", _
                    product.ProductID, product.ProductName, product.Category.CategoryName)
            Next

        End Using
    End Sub

    ' 追加
    Function Insert() As Integer
        Using tx As New TransactionScope
            Dim p As New Products()
            Using db As New NorthwindCTP
                p.ProductName = "Hoge"
                db.AddObject(p)
                db.SaveChanges()
            End Using
            tx.Complete()
            Return p.ProductID
        End Using
    End Function

    ' 更新
    Sub Update(ByVal productId As Integer)
        Using tx As New TransactionScope
            Using db As New NorthwindCTP
                Dim p As Products = CType(db.GetObjectByKey(db.CreateKey(GetType(Products), _
                            {New KeyValuePair(Of String, Object)("ProductID", productId)})), Products)
                p.ProductName = "Foo"
                db.SaveChanges()
            End Using
            tx.Complete()
        End Using
    End Sub

    ' 削除
    Sub Delete(ByVal productId As Integer)
        Using tx As New TransactionScope
            Using db As New NorthwindCTP
                Dim p As Products = CType(db.GetObjectByKey(db.CreateKey(GetType(Products), _
                            {New KeyValuePair(Of String, Object)("ProductID", productId)})), Products)
                db.DeleteObject(p)
                db.SaveChanges()
            End Using
            tx.Complete()
        End Using
    End Sub

End Module

eSQLというのはJPAでいうところのJPQLみたいなものらしい。
NorthwindCTPはSystem.Data.Objects.ObjectContextのサブクラスでJPAでいうところのEntityManagerみたいなものらしい。

IDでエンティティを取得するのにえらい長いコードを書かなければいけないのが気になります。でもこれはvNextのサンプル通りなのでたぶん正しいのだと思います。