1

ハンドソンテーブルのデータをデータベースに保存するための一般的に受け入れられているパターンはありますか?

ajax と WCF サービスを使用してデータベースからデータを取得し、テーブルにデータを入力しています。サービスは、データベース テーブルのデータ行を表すオブジェクトのリストを返しています。

WCF:

<ServiceContract(Namespace:="")>
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)>
Public Class TableService

    <OperationContract()>
    <WebGet(ResponseFormat:=WebMessageFormat.Json)>
    Public Function GetResource() As List(Of Resource)
        Dim conn = <some connection string>
        Dim sql = <some SQL>
        Dim dt = New DataTable("foo")

        Using da As New SqlDataAdapter(sql, conn)
            da.Fill(dt)
        End Using

        Return Objectify(dt)
    End Function

   Private Function Objectify(dt As DataTable) As List(Of Resource)
        Dim resourceTable = New List(Of Resource)

        For Each row As DataRow In dt.Rows
            resourceTable.Add(New Resource With {
                .ResourceAllocationID = row("ResourceAllocationID"),
                .ResourceName = row("ResourceName"),
                .AllocationPercent = row("AllocationPercent"),
                .Month = row("Month"),
                .Year = row("Year"),
                .Comments = row("Comments"),
                .ProjectID = row("ProjectID"),
                .ResourceUId = row("ResourceUId")})
        Next

        Return resourceTable
    End Function
End Class

Public Class Resource
    Public Property ResourceAllocationID As Integer
    Public Property ResourceName As String
    Public Property AllocationPercent As Integer
    Public Property Month As String
        Get
            Return _monthName
        End Get
        Set(value As String)
            Dim intMonth As Integer
            If Integer.TryParse(value, intMonth) Then
                If [Enum].IsDefined(GetType(MonthName), intMonth) Then
                    _monthName = CType(value, MonthName).ToString
                End If
            Else
                If [Enum].IsDefined(GetType(MonthName), value) Then
                    _monthName = value
                End If
            End If
        End Set
    End Property        
    Public Property Year As Integer
    Public Property Comments As String
    Public Property ProjectID As Integer
    Public Property ResourceUId As String

    Private _monthName As String

    Public Enum MonthName
        January = 1
        February = 2
        March = 3
        April = 4
        May = 5
        June = 6
        July = 7
        August = 8
        September = 9
        October = 10
        November = 11
        December = 12
    End Enum
End Class

Javascript:

$("#container").handsontable({
    contextMenu: true,
    startRows: 1,
    minRows: 1,
    colHeaders: ['Year', 'Month', 'Name', '% Allocation', 'Comments'],
    colWidths: [52, 100, 150, 100, 200],
    columns: [
        { data: 'Year', type: 'numeric' },
        { data: 'Month' },
        { data: 'ResourceName' },
        { data: 'AllocationPercent', type: 'numeric' },
        { data: 'Comments' }
    ]
});

$.ajax({
    url: "TableService.svc/GetResource",
    type: "GET",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (data) {
        $("#container").handsontable(loadData, data.d)
    },
    error: function (error) {
        alert("Error: " + error);
    }
});

これは、テーブルを埋めるために美しく機能します。私が苦労しているのは、変更をデータベースに保存する方法です。要件は、すべての変更が完了して更新ボタンが押されるまで、変更を保存しないことです。

を呼び出すことで、テーブル内のすべてのセルを含むオブジェクトを取得できることを知っていますhandsontable.getData()。私が考えているのは、オブジェクトを Json にシリアル化し、それをサービスに送り返し、逆シリアル化してオブジェクトのリストに戻し、リスト内の各オブジェクトのデータベースを更新する必要があるということです。私は正しい軌道に乗っていますか?もしそうなら、実際にどのように実装しますか?

4

2 に答える 2

3

そのため、特定の要件を満たすソリューションを組み合わせることになりました。

まず、Handsontable のすべてのセルを表す JSON 形式の文字列を取得して、WCF サービスに返す必要がありました。このメソッドhandsontable.getData()は、テーブル内のすべてのデータを表すオブジェクトを返します。次にJSON.stringify()、そのオブジェクトを文字列に変換していました。そこから、その文字列を自分のサービスに渡すのに問題がありました。オブジェクト内の引用符を適切にエスケープしながら、サービスの適切な文字列パラメーターを作成するには、既に文字列化されたオブジェクトを文字列化する必要があることが最終的にわかりました。

$("#btnUpdate").click(function () {
    var tableData = JSON.stringify(handsontable.getData());
    var input = JSON.stringify({ "input": tableData });

    $.ajax({
        type: 'POST',
        url: "TableService.svc/SaveResource",
        data: input,
        contentType: "application/json; charset=utf-8",
        dataType: 'json',
        success: function (res) {
            if (res.result === 'ok') {
                console.text('Data saved');
            }
        },
        error: function (xhr) {
            alert(xhr.responseText);
        }
    });
    $("btnUpdate").blur();
});

テーブル データがサーバー側に戻ったので、JSON を解析してオブジェクトのリストに戻す必要がありました。これを達成するためにJSON.NETを使用することになりました。DataTableオブジェクトのリストを作成したら、データベースの更新に必要な SQL を実行できるように、各リスト項目を new の行として追加しました。

<OperationContract()>
<WebInvoke(Method:="POST", BodyStyle:=WebMessageBodyStyle.WrappedRequest, ResponseFormat:=WebMessageFormat.Json)>
Public Function SaveResource(ByVal input As String) As String
    Dim resources As List(Of Resource) = Json.JsonConvert.DeserializeObject(Of List(Of Resource))(input)
    UpdateDB(resources)
    Return "ok"
End Function

Private Sub UpdateDB(resources As List(Of Resource))
    Dim dt As New DataTable
    Dim conn = <some connection string>
    Dim sql = <some SQL>
    Using da As New SqlDataAdapter(sql, conn)
        da.FillSchema(dt, SchemaType.Source)
        For Each resourceItem In resources
            Dim row As DataRow = dt.NewRow()
            Dim month As Resource.MonthName
            row("ResourceAllocationID") = resourceItem.ResourceAllocationID
            row("ResourceName") = resourceItem.ResourceName
            row("AllocationPercent") = resourceItem.AllocationPercent
            row("Month") = [Enum].TryParse(resourceItem.Month, month)
            row("Year") = resourceItem.Year
            row("Comments") = resourceItem.Comments
            row("ProjectID") = resourceItem.ProjectID
            row("ResourceUId") = resourceItem.ResourceUId
            dt.Rows.Add(row)
        Next
    End Using
    *<run the appropriate SQL on each row of dt to update the database>*
End Sub
于 2013-05-14T02:19:09.927 に答える
2

これには 2 つの方法があります。

  1. 小さな編集でデータを収集し、それらをブラウザーにローカルに保存します。ユーザーが保存をヒットすると、編集されたデータのチャンクがデータベースに送り返されます。

  2. データ テーブルのローカル バージョンを保持し、それを編集します。ユーザーが保存をヒットすると、テーブル全体が送り返され、データベースに保存されます。

チャーンが少なくなり、偶発的な上書きが発生しないため、アプローチ1を使用します。onChange コールバックを使用する必要があります。編集中の行の ID を持つ非表示の列が必要になると思います。

# coffeescript 
onChangeHandler = -> 
  rowChange = rowID: theDataArray[arguments[0]], rowCol: arguments[1], newVal: arguments[3], dateTime: new Date()
  window.MyNamespace.edits.push(rowChange)

tableDiv.handsontable
  ... 
  onChange: onChangeHandler 

$('#save').click( ->
 # save data back to the database
)
于 2013-05-06T17:52:47.673 に答える