ホーム > ASP.NET MVC 3, EF 4.1 Code First, mvcConf @:Japan > mvcConf @:Japan ふりかえり 5: 同時実行制御

mvcConf @:Japan ふりかえり 5: 同時実行制御

スライド15

CodeFirstとASP.NET MVCとの組み合わせでは同時実行制御も簡単に実装することができます。
ふりかえり1で作成したサンプルプログラムを同時実行制御のエラーチェックができるように修正してみましょう。

まず、POCOのクラスに以下のようにTimestamp属性を付加した制御用の項目を追加します

—————————————————————————————————–

public class Member
{
    public int ID { get; set; }
    [Required(ErrorMessage="名前は必須入力です")]
    public string Name { get; set; }
    [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "メールが正しくありません")]
    public string Mail { get; set; }
    public int CategoryID { get; set; }
    public DateTime? BirthDay { get; set; }
    public int? Age
    {
        get
        {
            int? age = null;
            if (BirthDay != null)
            {
                age = DateTime.Now.Year – BirthDay.Value.Year;
                if (DateTime.Now < BirthDay.Value.AddDays(-1).AddYears(age.Value)) age -= 1;
            }
            return age;
        }
    }
    [Timestamp]
    public Byte[] Timestamp { get; set; }

    public virtual Category Category { get; set; }

}

—————————————————————————————————–

これにより、データベースにTimestamp項目が追加されます。
データの型がByte[]型であることに注意しておきましょう。

スキャッフォールドで生成されるコントローラー、ビューはTimestamp項目がないときと同じです。
そのままだと更新時にエラーとなるので、Editビュー(Edit.cshtml)にhiddenとしてTimestamp項目を追加します。

—————————————————————————————————–

@model MyDal.Member

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Member</legend>

        @Html.HiddenFor(model => model.ID)

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Mail)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Mail)
            @Html.ValidationMessageFor(model => model.Mail)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.CategoryID, "Category")
        </div>
        <div class="editor-field">
            @Html.DropDownList("CategoryID", String.Empty)
            @Html.ValidationMessageFor(model => model.CategoryID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.BirthDay)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.BirthDay)
            @Html.ValidationMessageFor(model => model.BirthDay)
        </div>
        @Html.HiddenFor(Model => Model.Timestamp)
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

—————————————————————————————————–

同時実行制御のエラーが発生したときは例外としてDbUpdateConcurrencyExceptionがthrowされるので、このエラーをキャッチします。
実際のエラー時の対処はシステムの仕様によって異なります。
ここではとりあえずエラー時のメッセージを表示するようにだけEditアクションに手を入れます。

—————————————————————————————————–

[HttpPost]
public ActionResult Edit(Member member)
{
   try
    {
        if (ModelState.IsValid)
        {
            db.Entry(member).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
    }
    catch (DbUpdateConcurrencyException e)
    {
        ModelState.AddModelError(string.Empty, e.Message);
    }
    ViewBag.CategoryID = new SelectList(db.Categories, "CategoryID", "Name", member.CategoryID);
    return View(member);
}

—————————————————————————————————–

このようにサンプルプログラムを修正して実行します。
ブラウザを2つ起動して、片方でEdit画面を表示させた状態でもう1つのブラウザから同じデータを更新します。
その後、先にEdit画面を表示していたほうでデータを更新しようとすると以下のようなエラーが表示されます。

image

このサンプルで基本的な動作は理解していただけると思います。
より実際の動きに近い形の同時実行制御のサンプルがこちらで公開されています。
ぜひ参考にしてみてください。

  1. まだコメントはありません。
  1. 2011年6月22日 5:47 PM

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。