2012/09/20

【ASP.Net】MVC4で何か作ってみる その2【MVC】

 前回の続き。

 今回はCodeFirstでデータベースを準備します。さて早速ひとつ問題が…。MVC上のModelとEntityFramework上のModelを同一視しても良いものか?当然ながら連携面を考えた場合、同一のModelとして扱ってしまった方が楽なのは間違いなりませんし、チャートリアル等でもそのように扱われています。じゃあそうりゃいいじゃんって話なんですが、個人的にMVCとEntityFrameworkのどちらからしか使わない可能性のあるModelを作ることに抵抗があったりするわけで…。とりあえず今回はプロジェクトのModelsフォルダにDbフォルダを設け、EntityFrameworkのModelはそちらに書くことにします。

 さっそくModelの定義です。

社員テーブル
using System.ComponentModel.DataAnnotations;
 
namespace MVCTestProject.Models.Db
{
    /// <summary>
    /// 社員テーブル
    /// </summary>
    public class Employee
    {
 
        /// <summary>
        /// ID
        /// </summary>
        public int EmployeeId { get; set; }
 
        /// <summary>
        /// 社員名
        /// </summary>
        [MaxLength(50)]
        public string EmployeeName { get; set; }
 
        /// <summary>
        /// 配属先ID
        /// </summary>
        public int AssignId { get; set; }
 
        /// <summary>
        /// ソート順
        /// </summary>
        public decimal SortNumber { get; set; }
 
    }
}

配属先テーブル
using System.ComponentModel.DataAnnotations;
 
namespace MVCTestProject.Models.Db
{
    /// <summary>
    /// 配属先テーブル
    /// </summary>
    public class Assign
    {
 
        /// <summary>
        /// ID
        /// </summary>
        public int AssignId { get; set; }
 
        /// <summary>
        /// 配属先名
        /// </summary>
        [MaxLength(50)]
        public string AssignName { get; set; }
 
    }
}

コンテキスト
using System.Data.Entity;
using MVCTestProject.Models.Db;
 
namespace MVCTestProject
{
    /// <summary>
    /// データベースコンテキスト
    /// </summary>
    public class MvcTestContext : DbContext
    {
 
        /// <summary>
        /// MvcTestDbという名前でDbを作成
        /// </summary>
        public MvcTestContext()
            : base("MvcTestDb")
        { }
 
        public DbSet<Employee> Employees { get; set; }
 
        public DbSet<Assign> Assigns { get; set; }
 
    }
}

 データベースはとりあえずローカルに置くのでWeb.configは放置。変更が必要であればConnectionStringsタブなりEntityFrameworkタブなりに追記してください。

 あと、テストデータを用意したいのでConfigurationクラスを追加します。分からなければこの辺を参照してください。

ConfigurationクラスのSeedメソッド
protected override void Seed(MVCTestProject.MvcTestContext context)
{
    var employeeList = new List<Employee>();
 
    Parallel.For(0, 101, (n) =>
        {
            employeeList.Add(new Employee
                {
                    EmployeeName = (n % 2 != 0 ? n + "男" : n + "子"),
                    AssignId = (n % 2 != 0 ? 1 : 2),
                    SortNumber = n
                });
        });
 
    var target = employeeList.ToArray();
    context.Employees.AddOrUpdate(target);
 
    context.Assigns.AddOrUpdate(
        new Assign
            {
                AssignName = "A"
            },
        new Assign
            {
                AssignName = "B"
            });
}

 Emloyee型のリストを作成した後、わざわざ変数に突っ込んでるのは実行時にAddOrUpdateメソッドに「非静的メソッドはターゲットがうんぬん」と叱られるからです。これで下準備が完成です。

 今後、自力でビューを作っていくにあたってMVCがデータベースに対してどうゆう動作をするか知りたいと思います。なのでとりあえずコントローラーの作成時にEntityFrameworkと連携したテンプレートを選択してみます。

テンプレートやらモデル等を選択

2012092002

作成されたコントローラー
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVCTestProject.Models.Db;
 
namespace MVCTestProject.Controllers
{
    public class EmployeeController : Controller
    {
        private MvcTestContext db = new MvcTestContext();
 
        //
        // GET: /Employee/
 
        public ActionResult Index()
        {
            return View(db.Employees.ToList());
        }
 
        //
        // GET: /Employee/Details/5
 
        public ActionResult Details(int id = 0)
        {
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }
 
        //
        // GET: /Employee/Create
 
        public ActionResult Create()
        {
            return View();
        }
 
        //
        // POST: /Employee/Create
 
        [HttpPost]
        public ActionResult Create(Employee employee)
        {
            if (ModelState.IsValid)
            {
                db.Employees.Add(employee);
                db.SaveChanges();
                return RedirectToAction("Index");
            }
 
            return View(employee);
        }
 
        //
        // GET: /Employee/Edit/5
 
        public ActionResult Edit(int id = 0)
        {
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }
 
        //
        // POST: /Employee/Edit/5
 
        [HttpPost]
        public ActionResult Edit(Employee employee)
        {
            if (ModelState.IsValid)
            {
                db.Entry(employee).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(employee);
        }
 
        //
        // GET: /Employee/Delete/5
 
        public ActionResult Delete(int id = 0)
        {
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }
 
        //
        // POST: /Employee/Delete/5
 
        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(int id)
        {
            Employee employee = db.Employees.Find(id);
            db.Employees.Remove(employee);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
 
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

 あー、なんだか長くなっちゃいましたが、何となくはデータベースに対するアクセスの仕方が見えたのではないでしょうか?データベース→データ取得→ビューに渡すって単純な流れですね。

 一応、ビュー側も載せておきます。Razorは慣れないと違和感ありまくりですね。

Index.cshtml
@model IEnumerable<MVCTestProject.Models.Db.Employee>
 
@{
    ViewBag.Title = "Index";
}
 
<h2>Index</h2>
 
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.EmployeeName)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.AssignId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.SortNumber)
        </th>
        <th></th>
    </tr>
 
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.EmployeeName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.AssignId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.SortNumber)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.EmployeeId }) |
            @Html.ActionLink("Details", "Details", new { id=item.EmployeeId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.EmployeeId })
        </td>
    </tr>
}
 
</table>

 それでは今回はこの辺で…。次回は課題である結合したデータをビューに渡したり、それを利用して更新したりする予定です。






ビックカメラ.com
pagetop