Entity Framework

[もどる]


Entity Framework は LINQ To SQL より後に登場したフレームワークで、その分、LINQ To SQL より柔軟性があって高機能である。


サンプル1

このサンプルはクレジットカードの利用記録を検索して表示する Windows Forms アプリケーションである。

まず、プロジェクトを選択して、「追加 / 新規作成 / データ」から ADO.NET Entity Data Model を選択する。それから、以下の画像の手順で Entity Framework のデザイナを開いて、VISACARD テーブルをデータベースエクスプローラーからドラッグ&ドロップする。





フォームのソースを以下に示す。

''' <summary>
''' VISACARD フォーム
''' </summary>
Public Class Form1
    Private vc As VisacardClass

    ''' <summary>
    ''' フォームがロードしたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        DataGridView1.Dock = DockStyle.Fill
        vc = New VisacardClass()
    End Sub

    ''' <summary>
    ''' 検索ボタン
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnQuery_Click(sender As Object, e As EventArgs) Handles btnQuery.Click
        Try
            Cursor = Cursors.WaitCursor
            Dim strFrom As String = dtpFrom.Value.ToString("yyyy/MM/dd")
            Dim strTo As String = dtpTo.Value.ToString("yyyy/MM/dd")
            DataGridView1.DataSource = vc.Query(strFrom, strTo, txtShop.Text)
            StatusLabel1.Text = "検索されました。条件:" & strFrom & " - " & strTo & " " & txtShop.Text
        Catch ex As Exception
            MessageBox.Show("例外を検出。" & ex.Message, "エラー")
        End Try
        Cursor = Cursors.Default
    End Sub
End Class

 

フォームのコードでインスタンス化している VisacardClass クラスののソースを以下に示す。

''' <summary>
''' VISACARD 操作クラス
''' </summary>
Public Class VisacardClass
    ' User データベースエンティティ
    Private context As UserEntities

    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Public Sub New()
        context = New UserEntities
    End Sub

    ''' <summary>
    ''' 支払を検索する。
    ''' </summary>
    ''' <param name="fromDt">開始日</param>
    ''' <param name="toDt">終了日</param>
    ''' <param name="shop">ショップ</param>
    ''' <returns></returns>
    Public Function Query(ByVal fromDt As String, ByVal toDt As String, ByVal shop As String) As VISACARD()
        ' 日付パラメータが省略されていた場合の処理
        If String.IsNullOrEmpty(fromDt) Then
            fromDt = "1990/01/01"
        End If
        If String.IsNullOrEmpty(toDt) Then
            fromDt = "2100/01/01"
        End If

        ' 日付で絞り込み
        Dim rs As IQueryable(Of VISACARD) = From x In context.VISACARD Where x.DATE >= fromDt And x.DATE <= toDt

        ' ショップが省略されていない場合
        If Not String.IsNullOrEmpty(shop) Then
            rs = rs.Where(Function(x) x.SHOP.IndexOf(shop) = 0)
        End If

        ' 結果を返す。
        Return rs.ToArray()
    End Function
End Class

 

 

サンプル2

このサンプルは、ストアドプロシージャ(関数)を使って、パラメータで指定された期間の利用額と支払額の合計を計算している。テーブルは直接使っているが、カラムに別名を付けている。これは SELECT 文でカラムの別名を付けるのと同じ効果がある。




Module Module1
    ''' <summary>
    ''' Entity Framework を使用して利用合計と支払合計を求める。
    ''' </summary>
    ''' <param name="args"></param>
    Sub Main(ByVal args() As String)
        ' パラメータの確認
        If args.Length < 2 Then
            Console.WriteLine("パラメータとして開始日と終了日をYYYY/MM/DD形式で指定してください。")
            Return
        End If

        ' 合計額を求める。
        Dim context As New UserEntities
        Dim amount = context.SumAmountVisaCard(args(0), args(1))  ' Stored Procedure
        Dim vAmount As Decimal = amount.First().Value
        Console.WriteLine("利用額の合計 {0:C}", vAmount)

        Dim pay = context.SumOfPayVisaCard(args(0), args(1))  ' Stored Function
        Dim vPay As Decimal = pay.First().SumOfPay
        Console.WriteLine("支払額の合計 {0:C}", vPay)

        Console.WriteLine("終了。")
#If DEBUG Then
        Console.ReadKey()
#End If
    End Sub

End Module
 

 

サンプル3

 このサンプルはクレジットカード会社のサイトで利用額を検索し、そのとき CSV ファイルとしてダウンロードしたものをテーブルにインポートする Windows Forms アプリケーションである。Entity Framework のデザイン画面はサンプル2と同じである。


下の画像はこのアプリケーションの画面イメージである。


下の画像は「テーブルの内容を確認する」をクリックしたとき表示されるときの画面イメージである。


下のソースはインポートに必要なメソッドを実装したクラスである。変則的なデータ対応や全角文字を半角に変換するための処理が含まれている。


Imports System.IO
Imports System.Text

''' <summary>
''' VisaCard テーブル操作
''' </summary>
Public Class VisaCardClass
    Const USESQL = True

    ''' <summary>
    ''' CSV ファイルを VISACARD テーブルにインポートする。
    ''' </summary>
    ''' <param name="filePath">CSV ファイルのパス名</param>
    Public Shared Sub ImportCsv(ByVal filePath As String)
        Dim line As String
        Dim part(6) As String
        Dim lastDay As String = ""

        Using reader = New StreamReader(filePath, Encoding.Default)
            ' 先頭行を読み飛ばす。
            line = reader.ReadLine()
            ' ファイルの終わりまで繰り返す。
            While Not reader.EndOfStream
                ' 1行読み込む。
                line = reader.ReadLine()
                ' 要素に分解
                part = line.Split({","c})
                If String.IsNullOrEmpty(part(0)) Then
                    ' 先頭が空欄のとき(特殊な請求)
                    part(0) = If(String.IsNullOrEmpty(lastDay), "2000/01/01", lastDay)
                    ' 2番目の要素が空なら最終行(合計)なので無視する。
                    If String.IsNullOrEmpty(part(1)) Then
                        Continue While
                    End If
                Else
                    ' 先頭が日付のとき(通常の請求)
                    '  全角数字を半角に変換
                    part(3) = ToHalfPitch(part(3))
                    part(4) = ToHalfPitch(part(4))
                    lastDay = part(0)
                End If
                ' INSERT 文を実行する。
                InsertVisaCard(part)
            End While
        End Using
    End Sub

    ''' <summary>
    ''' 全角数字を半角数字に変換する。
    ''' </summary>
    ''' <param name="c"></param>
    ''' <returns></returns>
    Public Shared Function ToHalfPitch(ByVal c As String) As String
        Dim hc As Char
        Select Case c
            Case "0"c
                hc = "0"c
            Case "1"c
                hc = "1"c
            Case "2"c
                hc = "2"c
            Case "3"c
                hc = "3"c
            Case "4"c
                hc = "4"c
            Case "5"c
                hc = "5"c
            Case "6"c
                hc = "6"c
            Case "7"c
                hc = "7"c
            Case "8"c
                hc = "8"c
            Case "9"c
                hc = "9"c
            Case Else
        End Select
        Return hc
    End Function

    ''' <summary>
    ''' INSERT 文を得る。
    ''' </summary>
    ''' <param name="str">データ</param>
    Public Shared Sub InsertVisaCard(ByVal str() As String)
        str(2) = If(String.IsNullOrEmpty(str(2)), str(5), str(2))  ' 利用額が空欄なら請求額にする。
        str(3) = If((str(3) = vbNullChar) OrElse String.IsNullOrEmpty(str(3)), "0", str(3))      ' 利用回数がNULLなら'0'にする。
        str(4) = If((str(4) = vbNullChar) OrElse String.IsNullOrEmpty(str(4)), "0", str(4))      ' 利用区分がNULLなら'0'にする。
        Dim context As New UserEntities

        If USESQL Then
            ' 直接、SQL を実行してデータを挿入する。
            Dim sql As New StringBuilder
            sql.Append("INSERT INTO dbo.VISACARD([DATE],[SHOP],[AMOUNT],[PAYCLASS],[PAYCOUNT],[PAY],[INFO]) VALUES(")
            sql.Append("'" & str(0) & "',")
            sql.Append("N'" & str(1) & "',")
            sql.Append(str(2) & ",")
            sql.Append(str(3) & ",")
            sql.Append(str(4) & ",")
            sql.Append(str(5) & ",")
            sql.Append("N'" & str(6) & "')")
            context.Database.ExecuteSqlCommand(sql.ToString())
        Else
            ' Add, SaveChanges メソッドでデータを挿入する。
            Dim data As New VISACARD
            data.ID = 0
            data.日付 = str(0)
            data.ショップ = str(1)
            data.購入金額 = str(2)
            data.区分 = str(3)
            data.支払回数 = str(4)
            data.支払金額 = str(5)
            data.情報 = str(6)
            context.VISACARD.Add(data)
            context.SaveChanges()
        End If
    End Sub

    ''' <summary>
    ''' 最新の1000件を得る。
    ''' </summary>
    ''' <returns></returns>
    Public Shared Function GetLast1000() As VISACARD()
        Dim context As New UserEntities
        Dim rs = From x In context.VISACARD Select x Order By x.ID Descending
        rs.Take(1000)
        Return rs.ToArray()
    End Function
End Class