読者です 読者をやめる 読者になる 読者になる

1.21 jigowatts

Great Scott!

jqGridとEntity Frameworkの連携

概要

jQueryajaxメソッドによるPOST送信をジェネリックハンドラで受け取り処理を行うことにより、jqGridとEntity FrameworkによるSQLServerとの連携を行います。
f:id:sh_yoshida:20131013040232p:plain
f:id:sh_yoshida:20131013042007p:plain

手順

1.EDMを作成します。

ADO.NET Entity Data Modelを追加し、EDMを作成します。
作成したモデルよりデータベースを生成しSQLServerマッピングします。
f:id:sh_yoshida:20131013050308p:plain

2.jqGridからジェネリックハンドラに飛ばすように書き換えます。

datatypeプロパティを'local'からサーバー側の処理を得て受け取ったJSONデータを扱えるようにfunctionに変更します。

$("#momoclo").jqGrid({
    editurl: "/Service/MomocloHandler.ashx",
    datatype: function (postData) {
        //ajaxメソッドによるPOST通信の結果をjqGridに設定する
        $.ajax({
            type: "POST",
            url: "/Service/MomocloHandler.ashx",
            success: function (responseData) {
                //JSON形式の文字列をJavascriptオブジェクトに変換する
                var json_res = $.parseJSON(responseData);
                console.log("response:" + responseData);
                $("#momoclo")[0].addJSONData(json_res);
            }
        });
    },
    jsonReader: {
        page: "page",
        total: "total",
        records: "records",
        root: "data",
        repeatitems: false,
        id: "id"
    },
    width: 600,
    height: '100%',
    rownumbers: true,
    shrinkToFit: false,
    hidegrid: false,
    pager: "#pager",
    pgbuttons: false,
    pginput: false,
    viewrecords: true,
    colNames: ['id', '色', '名前', '誕生日', '血液型', '出身地', '身長'],
    colModel: [
                { 'name': 'id', 'index': 'id', 'width': 30, 'editable': true, 'hidden': true },//id列は非表示
                { 'name': 'color', 'width': 80, 'editable': true },
                { 'name': 'name', 'width': 130, 'editable': true },
                { 'name': 'birth',
                    'width': 90,
                    'editable': true,
                    'datefmt': "yyyy/mm/dd",
                    'editrules': { date: true },
                    'title': false
                },
                { 'name': 'bloodtype', 'width': 50, 'editable': true, 'edittype': "select", 'editoptions': { value: ":;0:A;1:B;2:AB;3:O" }, 'title': false },
                { 'name': 'birthplace', 'width': 80, 'editable': true },
                { 'name': 'height', 'width': 50, 'editable': true }
    ],
    caption: 'ももクロ',
    serializeRowData: function (data) {
        $.each(data, function (k, v) {
            console.log(k + ":" + v);
        });
      //編集データを渡します
      return data;
  }
});
$('#momoclo').jqGrid('navGrid', '#pager', { edit: false, add: false, del: true, search: false });
$('#momoclo').jqGrid('inlineNav', '#pager', {
  edit: true,
  editicon: "ui-icon-pencil",
  add: true,
  addicon: "ui-icon-plus",
  save: true,
  saveicon: "ui-icon-disk",
  cancel: true,
  cancelicon: "ui-icon-cancel",
  editParams: { oneditfunc: onEdit },
  addParams: {
      "rowID": 0, //id列の初期値←これを設定しないとid列が"jqg1"となってしまう
      "addRowParams": {
          oneditfunc: onEdit,
          successfunc: function (response) {
              //データ追加後リロードしないとid列が0のままとなってしまう
              $('#momoclo').trigger("reloadGrid"); 
              return true;
          }
      }
  }
});
function onEdit(id) {
  $("#" + id + "_birth").datepicker({
      changeMonth: true,
      changeYear: true,
      dateFormat: 'yy/mm/dd',
      yearRange: '1970:2100'
  }).addClass("grid-datepicker");
}

3.ジェネリックハンドラを用意します。

MomocloHandler.ashx.csを作成します。
POSTで受け取った[oper]の内容で処理を振り分けます。

using System.Transactions;
using System.Web;
using Momoclo.DAO;
using Momoclo.Util;
using Momoclo.View;

namespace Momoclo.Service
{
    public class MomocloRequest
    {
        public int id { get; set; }
        public string color { get; set; }
        public string name { get; set; }
        public string birth { get; set; }
        public string bloodtype { get; set; }
        public string birthplace { get; set; }
        public string height { get; set; }
        public string oper { get; set; }
    }

    /// <summary>
    /// MomocloHandler の概要の説明
    /// </summary>
    public class MomocloHandler : IHttpHandler
    {
        private const string ADD = "add";
        private const string EDIT = "edit";
        private const string DEL = "del";
        HttpContext context;
        MomocloRequest req = new MomocloRequest();

        public void ProcessRequest(HttpContext context)
        {
            this.context = context;

            if (context.Request.HttpMethod == "GET")
            {
                System.Diagnostics.Debug.WriteLine("GET");

            }
            else if (context.Request.HttpMethod == "POST")
            {
                System.Diagnostics.Debug.WriteLine("POST");
                
                string id = context.Request.Form["id"];
                req.id = int.Parse(Utility.NullToZero(id));       
                
                req.color = context.Request.Form["color"];
                req.name = context.Request.Form["name"];
                req.birth = context.Request.Form["birth"];
                req.bloodtype = context.Request.Form["bloodtype"];
                req.birthplace = context.Request.Form["birthplace"];
                req.height = context.Request.Form["height"];
                req.oper = context.Request.Form["oper"];

            }

            switch (req.oper) 
            {
                case ADD:
                    Save();
                    break;
                case EDIT:
                    Save();
                    break;
                case DEL:
                    Remove();
                    break;
                default:
                    Load();
                    break;
            }
          
        }

        private void Load()
        {
            context.Response.ContentType = "text/plain";

            var s = new System.Web.Script.Serialization.JavaScriptSerializer();
            MomocloDAO dao = new MomocloDAO();
            MemberView[] members = dao.Select();
            context.Response.Write(s.Serialize(members));
            context.Response.End();
        }

        private void Save()
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                MomocloDAO dao = new MomocloDAO();
                dao.Save(req);
                transaction.Complete();
            }
        }

        private void Remove()
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                MomocloDAO dao = new MomocloDAO();
                dao.Remove(req);
                transaction.Complete();
            }
        }
    }
}

4.データ処理クラスを用意します。

オブジェクトコンテキスト生成

namespace Momoclo.Common
{
    public class DBUtil
    {
        private MomocloEDMContainer container;

        public MomocloEDMContainer MContainer {
            get 
            {
                if (container == null)
                {
                    container = new MomocloEDMContainer();
                }
                return container;
            }
        }
    }
}

#後日追記
現在開発中プロジェクトのフレームワークに従ってこのような書き方をしてしまいましたが、このオブジェクトコンテキストの使い方は問題が起きました。
なんちゃってシングルトンのため、ひとつのオブジェクトコンテキストのインスタンスを使い続けることによって、トランザクションに影響を及ぼしてしまいます。
オブジェクトコンテキストを使う場合はusingステートメントで囲んで、都度インスタンスを生成し、使うよう修正しています。


CRUD処理を書きます。

using System.Collections.Generic;
using System.Linq;
using Momoclo.Common;
using Momoclo.Service;
using Momoclo.Util;
using Momoclo.View;

namespace Momoclo.DAO
{
    public class MomocloDAO : DBUtil
    {
        public MemberView[] Select() 
        {
            var rs = from mem in this.MContainer.Members
                     select mem;
            //jqGridの項目名に合わせてマッピング
            List<MemberView> members = new List<MemberView>();
            foreach (Member member in rs)
            {
                MemberView view = new MemberView();
                view.id = member.ID;
                view.color = member.Color;
                view.name = member.Name;
                view.birth = member.Birth;
                view.bloodtype = getBloodtype(member.Bloodtype);
                view.birthplace = member.Birthplace;
                view.height = member.Height.ToString();
                members.Add(view);
            }

            return members.ToArray();

        }

        public void Save(MomocloRequest req)
        {

            if (req.id > 0)
            {   //更新
                var rs = from mem in this.MContainer.Members
                         where mem.ID == req.id
                         select mem;

                Member oldRec = rs.Single();

                oldRec.Color = req.color;
                oldRec.Name = req.name;
                oldRec.Birth = req.birth;
                oldRec.Bloodtype = req.bloodtype;
                oldRec.Birthplace = req.birthplace;
                oldRec.Height = Utility.NullorValue(req.height);
            }
            else 
            {   //新規登録
                Member member = new Member();
                member.Color = req.color;
                member.Name = req.name;
                member.Birth = req.birth;
                member.Bloodtype = req.bloodtype;
                member.Birthplace = req.birthplace;
                member.Height = Utility.NullorValue(req.height);

                this.MContainer.Members.AddObject(member);            
            }

            this.MContainer.SaveChanges();

        }

        public void Remove(MomocloRequest req)
        {
            var rs = from mem in this.MContainer.Members
                     where mem.ID == req.id
                     select mem;

            this.MContainer.Members.DeleteObject(rs.Single());

            this.MContainer.SaveChanges();
      
        }

        private string getBloodtype(string s) 
        {
            switch(s){
                case "0":
                    return "A";
                case "1":
                    return "B";
                case "2":
                    return "AB";
                case "3":
                    return "O";
                default :
                    return null;
            }
        }
    }
}

5.データベース定義とjqGridの定義をマッピングするクラスを用意します。

jqGridでは項目の定義を小文字、SQLServerでは項目の定義を頭文字大文字で定義しているため、jqGridの項目名にマッピングして返します。

namespace Momoclo.View
{
    public class MemberView
    {
        public int id { get; set; }
        public string color { get; set; }
        public string name { get; set; }
        public string birth { get; set; }
        public string bloodtype { get; set; }
        public string birthplace { get; set; }
        public string height { get; set; }
    }
}

完成

f:id:sh_yoshida:20131013040232p:plain
f:id:sh_yoshida:20131013042007p:plain