2016年9月2日金曜日

ASP.NET MVC5(VB) 【Entity Frame Workを使用しないでCRUD】

Entity Frame Workを使用しないで、昔ながらのADO.NETの記述方法でデータベースの基本操作をしようと、チュートリアルを探したところ、以下のサイトがありました。(英語サイト)

CRUD Operations In ASP.NET MVC5 Using ADO.NET

同様の内容を、VBでコーディングしてみました。

開発環境:Visual Studio Community 2015(VB)、SQLServer2008R2



  1. 新しいプロジェクトの作成

    「ASP.NET Webアプリケーション」を選択して「OK」、


    テンプレートとして「Empty」を選択し、フォルダー及びコア参照の部分で「MVC」にのみチェックを入れて「OK」


    ソリューションが作成されます。
  2. モデルクラスの作成

    モデルフォルダを右クリックし、「追加」、「クラス」の順に選択します。


    「EmpModel.vb」と名前を付けて、空のクラスを作成します。


    以下のコードを入力します。
    Imports System.ComponentModel
    Imports System.ComponentModel.DataAnnotations
    
    Public Class EmpModel
    
        <DisplayName("ID")>
        Public Property Empid As Integer
    
        <Required(ErrorMessage:="名前を入力して下さい")>
        Public Property Name As String
    
        <Required(ErrorMessage:="都市名を入力して下さい")>
        Public Property City As String
    
        <Required(ErrorMessage:="住所を入力して下さい")>
        Public Property Address As String
    
    End Class
    
    
  3. コントローラークラスの作成

    コントローラーフォルダを右クリックし、「追加」、「コントローラー」の順に選択します。


    「読み取り/書き込みアクションがある MVC5コントローラー」を選択します。


    「EmproyeeContoroller」と名付けます。


    CRUDを行うテンプレートのコードが、自動生成されます。
  4. テーブルの作成

    接続先のSQLServerのデータベースにテーブルを作成します。
    テーブル名は「Emproyee」とします。
    ※SQLServerManagementStudioを用いてテーブルを作成しました。

    CREATE TABLE [dbo].[Employee](
     [Id] [int] NOT NULL PRIMARY KEY,
     [Name] [varchar](50) NULL,
     [City] [varchar](50) NULL,
     [Address] [varchar](50) NULL
     )
    

    元のチュートリアルではレコード操作用のストアドプロシージャを作成していますが、ここではストアドプロシージャは作成せず、SQL文を都度発行するスタイルで作ります。
  5. レポジトリの作成
    データベース関連の処理をするレポジトリクラスを作成します。
    まずはソリューションに「Repository」フォルダを作成します。


    続いて、「Repository」フォルダを右クリックし、「追加」、「クラス」の順に選択し、「EmpRepository.vb」と名前を付けてクラスを作成します。


    レポジトリクラスに、データの一覧取得、追加、更新、削除のメソッドを記述します。

    Imports System.Data.SqlClient
    
    Public Class EmpRepository
    
        Private con As SqlConnection
    
        '-----------------------------------------------
        '   SqlConnection                               
        '-----------------------------------------------
        Private Sub connection()
            Dim constr As String = ConfigurationManager.ConnectionStrings("getconn").ToString
            con = New SqlConnection(constr)
        End Sub
    
        '-----------------------------------------------
        '   データの追加
        '-----------------------------------------------
        Public Function AddEmployee(obj As EmpModel) As Boolean
    
            connection()
    
            Dim strSQL As String = String.Empty
            strSQL &= "INSERT   INTO    Employee    " & vbCrLf
            strSQL &= "VALUES(  @ID,                " & vbCrLf
            strSQL &= "         @NAME,              " & vbCrLf
            strSQL &= "         @CITY,              " & vbCrLf
            strSQL &= "         @ADDRESS            " & vbCrLf
            strSQL &= "         )                   " & vbCrLf
    
            Dim com As New SqlCommand(strSQL, con)
            com.CommandType = CommandType.Text
    
            'パラメータをセット
            com.Parameters.AddWithValue("@ID", obj.Empid)
            com.Parameters.AddWithValue("@NAME", obj.Name)
            com.Parameters.AddWithValue("@CITY", obj.City)
            com.Parameters.AddWithValue("@ADDRESS", obj.Address)
    
            con.Open()
            Dim i As Integer = com.ExecuteNonQuery
            con.Close()
    
            If i >= 1 Then
                Return True
            Else
                Return False
            End If
    
        End Function
    
        '-----------------------------------------------
        '   データの一覧
        '-----------------------------------------------
        Public Function GetAllEmployees() As List(Of EmpModel)
    
            connection()
    
            Dim EmpList As List(Of EmpModel) = New List(Of EmpModel)
            Dim strSQL As String = String.Empty
            strSQL &= "SELECT   Id,Name,City,Address" & vbCrLf
            strSQL &= "FROM     Employee            " & vbCrLf
            strSQL &= "ORDER BY ID                  " & vbCrLf
    
            Dim com As New SqlCommand(strSQL, con)
            com.CommandType = CommandType.Text
    
            Dim da As New SqlDataAdapter(com)
            Dim dt As DataTable = New DataTable
    
            con.Open()
            da.Fill(dt)
            con.Close()
    
            '読み込んだ値をListにセット
            For Each dr As DataRow In dt.Rows
                Dim Record As New EmpModel
                With Record
                    .Empid = CInt(dr.Item("Id"))
                    .Name = dr.Item("Name").ToString
                    .City = dr.Item("City").ToString
                    .Address = dr.Item("Address").ToString
                End With
                EmpList.Add(Record)
            Next
    
            Return EmpList
    
        End Function
    
        '-----------------------------------------------
        '   既存データの更新
        '-----------------------------------------------
        Public Function UpdateEmployee(Id As Integer, obj As EmpModel) As Boolean
    
            connection()
    
            Dim strSQL As String = String.Empty
            strSQL &= "UPDATE   Employee                  " & vbCrLf
            strSQL &= "SET      Id = @ID ,                " & vbCrLf
            strSQL &= "         Name = @NAME,             " & vbCrLf
            strSQL &= "         City = @CITY,             " & vbCrLf
            strSQL &= "         Address = @ADDRESS        " & vbCrLf
            strSQL &= "WHERE    Id = @UPDID               " & vbCrLf
    
            Dim com As New SqlCommand(strSQL, con)
            com.CommandType = CommandType.Text
    
            'パラメータをセット
            com.Parameters.AddWithValue("@ID", obj.Empid)
            com.Parameters.AddWithValue("@NAME", obj.Name)
            com.Parameters.AddWithValue("@CITY", obj.City)
            com.Parameters.AddWithValue("@ADDRESS", obj.Address)
            com.Parameters.AddWithValue("@UPDID", Id)
    
            con.Open()
            Dim i As Integer = com.ExecuteNonQuery
            con.Close()
    
            If i >= 1 Then
                Return True
            Else
                Return False
            End If
    
        End Function
    
        '-----------------------------------------------
        '   既存データの削除
        '-----------------------------------------------
        Public Function DeleteEmployee(Id As Integer) As Boolean
    
            connection()
    
            Dim strSQL As String = String.Empty
            strSQL &= "DELETE   Employee    " & vbCrLf
            strSQL &= "WHERE    Id = @ID    " & vbCrLf
    
            Dim com As New SqlCommand(strSQL, con)
            com.CommandType = CommandType.Text
    
            'パラメータをセット
            com.Parameters.AddWithValue("@ID", Id)
    
            con.Open()
            Dim i As Integer = com.ExecuteNonQuery
            con.Close()
    
            If i >= 1 Then
                Return True
            Else
                Return False
            End If
    
        End Function
    
    End Class
    
    ルートフォルダの「Web.config」に"getconn"の名前で接続文字列を定義します。 ※各自の環境に合わせて記述して下さい。
  6. コントローラーにメソッドを記述

    Option Strict Off   '※OnだとViewBagの記述時に遅延バインディングエラー
    
    Imports System.Web.Mvc
    
    Namespace Controllers
        Public Class EmployeeController
            Inherits Controller
    
            '-----------------------------------------------
            '   データの一覧画面表示
            '-----------------------------------------------
            ' GET: Employee
            Function Index() As ActionResult
                Dim EmpRepo As New EmpRepository
                ModelState.Clear()
                Return View(EmpRepo.GetAllEmployees)
            End Function
    
            '-----------------------------------------------
            '   データの詳細取得
            '-----------------------------------------------
            ' GET: Employee/Details/5
            Function Details(ByVal id As Integer) As ActionResult
                Dim EmpRepo As New EmpRepository
                Return View(EmpRepo.GetAllEmployees().Find(Function(a) a.Empid = id))
            End Function
    
            '-----------------------------------------------
            '   データの追加画面表示
            '   ※入力画面=空データ
            '-----------------------------------------------
            ' GET: Employee/Create
            Function Create() As ActionResult
                Return View()
            End Function
    
            '-----------------------------------------------
            '   データの追加
            '-----------------------------------------------
            ' POST: Employee/Create
            
            Function Create(Emp As EmpModel) As ActionResult
                Try
                    ' TODO: Add insert logic here
                    If ModelState.IsValid Then
                        Dim EmpRepo As New EmpRepository
                        If EmpRepo.AddEmployee(Emp) Then
                            ViewBag.Message = "データの登録に成功しました"
                        End If
                    End If
                    Return RedirectToAction("Index")
                Catch
                    Return View()
                End Try
            End Function
    
            '-----------------------------------------------
            '   既存データの編集画面表示
            '-----------------------------------------------
            ' GET: Employee/Edit/5
            Function Edit(ByVal id As Integer) As ActionResult
                Dim EmpRepo As New EmpRepository
                Return View(EmpRepo.GetAllEmployees().Find(Function(a) a.Empid = id))
            End Function
    
            '-----------------------------------------------
            '   既存データの更新
            '-----------------------------------------------
            ' POST: Employee/Edit/5
            <HttpPost()>
            Function Edit(ByVal id As Integer, Emp As EmpModel) As ActionResult
                Try
                    ' TODO: Add update logic here
                    Dim EmpRepo As New EmpRepository
                    EmpRepo.UpdateEmployee(id, Emp)
                    Return RedirectToAction("Index")
                Catch
                    Return View()
                End Try
            End Function
    
            '-----------------------------------------------
            '   データの削確認除画面表示
            '-----------------------------------------------
            ' GET: Employee/Delete/5
            Function Delete(ByVal id As Integer) As ActionResult
                Dim EmpRepo As New EmpRepository
                Return View(EmpRepo.GetAllEmployees().Find(Function(a) a.Empid = id))
            End Function
    
            '-----------------------------------------------
            '   データの削除
            '-----------------------------------------------
            ' POST: Employee/Delete/5
            
            Function Delete(ByVal id As Integer, ByVal collection As FormCollection) As ActionResult
                Try
                    ' TODO: Add delete logic here
                    Dim EmpRepo As New EmpRepository
                    If EmpRepo.DeleteEmployee(id) Then
                        ViewBag.AlertMsg = "データを削除しました。"
                    End If
                    Return RedirectToAction("Index")
                Catch
                    Return View()
                End Try
            End Function
    
        End Class
    
    End Namespace
    
  7. ビューの作成

    作成したコントローラーに対応するビューを作成(自動生成)します。
    コントローラーのメソッド内で右クリックし「ビューを追加」を選択します。


    ビューの追加画面が表示されるので、
    テンプレート欄には
    ・Indexメソッドには「Create」
    ・Deteilsメソッドには「Details」
    ・Createメソッドには「Create」
    ・Editメソッドには「Edit」
    ・Deleteメソッドには「Delete」
    をそれぞれ選択します。

    また、モデルクラス欄には「EmpModel」を選択し、オプションの「部分ビューとして作成」にチェックを入れて「追加」を押します。


    Index、Details、Create、Edit、Deleteの5つのメソッドに対してビューを作成します。
  8. ビュー「Index.vbhtml」の修正
    初期状態ではコメントアウトされているEdit、Details、Editのリンク部分を修正します。

    初期状態


    修正後
                @Html.ActionLink("Edit", "Edit", New With {.id = item.Empid}) |
                @Html.ActionLink("Details", "Details", New With {.id = item.Empid}) |
                @Html.ActionLink("Delete", "Delete", New With {.id = item.Empid})



  9. ルーティング設定
    「App_Start」フォルダ内の「RouteConfig.vb」を修正します。


    デフォルトのコントローラーを「Employee」にし、デフォルトアクションを「Index」にします。


    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Web
    Imports System.Web.Mvc
    Imports System.Web.Routing
    
    Public Module RouteConfig
        Public Sub RegisterRoutes(ByVal routes As RouteCollection)
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
    
            routes.MapRoute(
                name:="Default",
                url:="{controller}/{action}/{id}",
                defaults:=New With {.controller = "Employee", .action = "Index", .id = UrlParameter.Optional}
            )
        End Sub
    End Module
    
ここまでで一通り完成です。
実行して、動作を確認してみて下さい。