【问题标题】:How to update two tables with one dataset?如何用一个数据集更新两个表?
【发布时间】:2013-04-25 15:29:27
【问题描述】:

我有一个数据集,其中包含来自两个 SQL 表的数据。

如何使用更新后的数据集更新两个表? (因为加入不起作用)

             da = new SqlDataAdapter("select * from xxxx join.....", conn);
             builderForTable1 = new SqlCommandBuilder(da);
             da.Update(dataSetEmp, "Table");

【问题讨论】:

    标签: c# sql save sql-update


    【解决方案1】:

    如果您提供给数据适配器的查询返回多个结果集,则 SQLDataAdapter.Fill() 方法可以执行此操作。

    var da = new SqlDataAdapter("select * from customers; select * from orders;", conn);
    da.Fill(myDataset);
    
    var customersDataTable = myDataset.Tables[0];
    var ordersDataTable = myDataset.Tables[1];
    

    然后您可以根据需要添加自己的 DataRelations。

    myDataset.Relations.Add(new DataRelation(
        "CustomerOrders",
        customersDataTable.Columns["CustomerID"],
        ordersDataTable.Columns["CustomerID"]
    )
    

    【讨论】:

    • 如果你不返回多个结果集?因为两个表都在一个结果集中...
    • 如果将两个表连接到一个结果集中,那么 .net 会将其视为一个结果集并仅加载一个表。如果要加载两个表,则需要提供两个结果集或使用数据读取器并显式循环遍历结果集,随时填充表。 (使用两个结果集更简单、更简洁。)
    • 太棒了。整洁的做法。谢谢
    【解决方案2】:
    Public Shared Function GetRecords(ByRef CNobj As System.Data.SqlClient.SqlConnection,
                                       ByRef RSobj As System.Data.DataSet,
                                       ByVal SQLquery As String,
                                       ByVal TableName() As String,
                                       Optional ByVal PrimKeys() As String = Nothing,
                                       Optional ByRef adapter As SqlDataAdapter = Nothing) As Integer
    
        On Error Resume Next
        Dim DataOkay As Integer = 0                             '[Set to negative if data bad]
    
        Dim suppliersAdapter As SqlDataAdapter = New SqlDataAdapter()
    
        'Create connection object, won't create if already exists
        If ConnectToDB(CNobj, False) = False Then
            'error creating object, Session("ErrorMsg") set by called code
            Return -1
        End If
    
        ' Open the connection.
        If CNobj.State = ConnectionState.Closed Then
            CNobj.Open()
        End If
    
    
        ' Create a SqlCommand to retrieve Suppliers data.
        Dim suppliersCommand As SqlCommand = New SqlCommand(SQLquery, CNobj)
    
        suppliersCommand.CommandType = CommandType.Text
    
        ' Set the SqlDataAdapter's SelectCommand.
        suppliersAdapter.SelectCommand = suppliersCommand
    
    
        ' Fill the DataSet.
        RSobj = New DataSet()
        suppliersAdapter.Fill(RSobj)
        If (Err.Number <> 0) Then
            DataOkay = -1
            _contexts.Session("ErrorMsg") = "Error reading records: " +
                DelDoubleQuotesInString(Err.Description)
            Call Err.Clear()
        ElseIf (RSobj.Tables.Count = 0) Then
            DataOkay = -2
            _contexts.Session("ErrorMsg") = "No tables read reading records for sql=" + SQLquery
        Else
            ' A table mapping names the DataTables.
            Dim IDX As Integer
            For IDX = 0 To TableName.Count - 1
                RSobj.Tables(IDX).TableName = TableName(IDX)
                If PrimKeys IsNot Nothing Then
                    Dim primstr = PrimKeys(IDX)
                    Dim primarr = Split(primstr, ",")
                    Dim primcol(primarr.Count) As DataColumn
                    Dim pidx As Integer
                    For pidx = 0 To primarr.Count
                        primcol(pidx) = RSobj.Tables(IDX).Columns.Item(primarr(pidx))
                    Next
                    RSobj.Tables(IDX).PrimaryKey = primcol
                End If
    
            Next
            adapter = suppliersAdapter
        End If
        Return DataOkay
    End Function
    
      Public Shared Function UpdateDB(ByRef dset As System.Data.DataSet, ByVal adapter As SqlDataAdapter)
        If dset.HasChanges = False Then
            Return True
        End If
        ' has multiple tables, select's separated by ;
        Dim SelectQry As String = adapter.SelectCommand.CommandText
        Dim commands() As String = Split(SelectQry, ";")
        Dim idx As Integer = 0
    
        For Each Table As System.Data.DataTable In dset.Tables
            'Connection object is global in shared ASP.NET module
            If CNobj.State = ConnectionState.Closed Then
                CNobj.Open()
            End If
            'Change select for table being updated.
            adapter.SelectCommand.CommandText = commands(idx)
    
    
            Dim cb As SqlCommandBuilder
            cb = New SqlCommandBuilder(adapter)
    
            adapter.InsertCommand = cb.GetInsertCommand(True)
            adapter.UpdateCommand = cb.GetUpdateCommand(True)
            adapter.DeleteCommand = cb.GetDeleteCommand(True)
    
            Try
    
                adapter.AcceptChangesDuringUpdate = True
                'force order delete, update, insert
                adapter.Update(Table.Select(Nothing, Nothing, DataViewRowState.Deleted))
                Table.AcceptChanges() 'Have to do after delete!
                adapter.Update(Table.Select(Nothing, Nothing, DataViewRowState.ModifiedCurrent))
                adapter.Update(Table.Select(Nothing, Nothing, DataViewRowState.Added))
            Catch
                HttpContext.Current.Session("ErrorMsg") = "Error saving data to DB: " + Err.Description
                adapter.SelectCommand.CommandText = SelectQry
                Return False
            End Try
            idx += 1
            cb.Dispose()
        Next
        'Put original select back for next call
        adapter.SelectCommand.CommandText = SelectQry
        Return True
    End Function
    

    我包含了我正在使用的两个例程。如果使用带分号的 select 调用,第一个例程将获得多个表。我传入表名数组以分配给每个表。如果数据集要更新到服务器,那么我还将传入主键和对适配器的引用以传递给更新调用。

    我知道它是在 VB 而不是 C# 中,但是我正在转换为 ASP.NET 的 Classic ASP 已经在 VB 中,我不想在它之上移植到 C#。

    更新代码为每个表的每个更新调用拆分选择字符串。

    错误 - 上述代码不适用于所有表格。对于一张表,如果我不接受更改,它将不会更新 - 出现并发错误。在另一张表上,它指出我在调用 acceptchanges 之前修改了 13 行 - 但在调用后变为零,因此没有更新记录。我的猜测是,为一个出现并发错误的表生成的更新 SQL 是废话,不应该调用 acceptchanges。当我解决这个问题时,我会更新帖子。

    【讨论】:

      【解决方案3】:

      也许你可以使用交易?

      SqlTransaction tr = conn.BeginTransaction();
          da = new SqlDataAdapter("select * from xxxx join.....", conn);
          builderForTable1 = new SqlCommandBuilder(da);
          da.Update(dataSetEmp, "Table");
          // ...
      tr.Commit();
      

      参考:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        • 1970-01-01
        • 2023-01-11
        • 2013-07-04
        • 1970-01-01
        • 2016-02-20
        • 2011-06-29
        相关资源
        最近更新 更多