如何将Handsontable保存到数据库

时间:2013-04-30 16:19:18

标签: vb.net json wcf jquery handsontable

是否存在一种普遍接受的模式,用于将数据保存在数据库中,以便将数据保存回数据库?

我正在使用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

Javacript:

$("#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,将其发送回我的服务,将其反序列化为对象列表,然后为列表中的每个对象更新数据库。我是在正确的轨道上吗?如果是这样,我该如何实际实现呢?

2 个答案:

答案 0 :(得分:3)

所以,我最终拼凑出一个满足我特定要求的解决方案。

我首先需要获取一个JSON格式的字符串,表示Handsontable的所有单元格,以传递回我的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。

<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

答案 1 :(得分:2)

有两种方法可以解决这个问题:

  1. 以小编辑方式收集数据,在浏览器中本地保存,当用户点击保存时,您将编辑后的数据块发送回数据库。

  2. 保留数据表的本地版本,编辑它,当用户点击保存时,您将整个表发回并将其保存到数据库中。

  3. 我会使用方法1,因为它会减少流失,你不会意外覆盖。您需要使用onChange callback。我认为你需要有一个隐藏的列,其中包含您正在编辑的行的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
    )