PRB:CommandBuilder 将修改后的命令复原

文章翻译 文章翻译
文章编号: 310366 - 查看本文应用于的产品
本文的发布号曾为 CHS310366
本文已归档。它按“原样”提供,并且不再更新。
本文引用下面的 Microsoft .NET 框架类库名称空间:
  • System.Data.SqlClient
展开全部 | 关闭全部

本文内容

症状

在下一次调用 DataAdapter.Update 方法时,CommandBuilder 对象可能重新生成您尝试修改的命令,因此您对该命令所作的更改可能会丢失。以下情况下可能会发生此问题:
  • 如果您将一个 CommandBuilder 对象和一个 DataAdapter 对象关联了起来。
  • 如果您使用 CommandBuilder 对象的 GetInsertCommandGetUpdateCommandGetDeleteCommand 方法显式地将命令分配给 DataAdapter
  • 如果您修改 CommandBuilder 生成的一个命令。
当您尝试调用 DataAdapter Update 方法时,可能会收到以下错误信息:
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in system.data.dll

原因

发生此问题的原因是,CommandBuilder 动态地将它所生成的命令重新改成了原来的命令。

解决方案

可使用以下方法之一解决此问题:
  • 不要修改 CommandBuilder 生成的命令。CommandBuilder 不会更改您自己生成的命令对象。
  • InsertCommandDeleteCommandUpdateCommand 对象复制到一个新的 DataAdapter 中(有关示例,请参见"更多信息"部分)。新的 DataAdapter 变量的范围必须小于或等于旧的 DataAdapter 变量的范围。
  • 不要使用 CommandBuilder。编写您自己的命令对象,或者使用 Visual 数据工具编写命令对象。

状态

这种现象是设计使然。

更多信息

再现现象的步骤

  1. 新建一个 Visual Basic Windows 应用程序项目。默认情况下会将 Form1 添加到项目中。
  2. 双击该窗体,将下面的代码添加到"代码"窗口的顶部:
    Imports System.Data.SqlClient
  3. 在 Form1 上添加一个按钮控件。
  4. 双击该按钮,然后将下面的代码添加到 Click 事件中:
    Dim cn As New SqlConnection()
    Dim custDS As New DataSet()
    Dim da1 As New SqlDataAdapter()
    Dim da2 As New SqlDataAdapter()
    Dim dr As DataRow
    Dim cb As SqlCommandBuilder
    
    cn.ConnectionString = "server=servername;database=northwind;uid=sa;pwd=password;"
    cn.Open()
    da1 = New SqlDataAdapter("select * from Customers", cn)
    cb = New SqlCommandBuilder(da1)
    
    da1.Fill(custDS, "Customers")
    
    'Get the original commands.
    
    da1.InsertCommand = cb.GetInsertCommand
    da1.DeleteCommand = cb.GetDeleteCommand
    da1.UpdateCommand = cb.GetUpdateCommand
    
    Debug.WriteLine("Original command length:" & da1.InsertCommand.CommandText.Length)
    
    'Modify the Insert command.
    
    da1.InsertCommand.CommandText = "select * from customers where customerid=@@identity"
    
    da1.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord
    
    da2.InsertCommand = da1.InsertCommand
    da2.DeleteCommand = da1.DeleteCommand
    da2.UpdateCommand = da1.UpdateCommand
    
    'Add a record to the table.
    
    Dim tblCust As DataTable
    tblCust = custDS.Tables("Customers")
    
    Dim drCust As DataRow
    
    drCust = tblCust.NewRow()
    drCust("CustomerID") = "ZYYYY"
    drCust("CompanyName") = "Zora's Yummies"
    drCust("ContactName") = "Christophe Namby"
    drCust("ContactTitle") = "Assistant Manager"
    
    tblCust.Rows.Add(drCust)
    
    'Update the backend.
    
    Debug.WriteLine("Length da1 before insert:" & da1.InsertCommand.CommandText.Length)
    
    da1.Update(custDS, "Customers")
    
    Debug.WriteLine("Length da1 after insert:" & da1.InsertCommand.CommandText.Length)
    Debug.WriteLine("length da2 before insert:" & da2.InsertCommand.CommandText.Length)
    
    da2.Update(custDS, "Customers")
    
    Debug.WriteLine("Length da2 after insert:" & da2.InsertCommand.CommandText.Length)
  5. 将连接字符串修改为连接到您的 Microsoft SQL Server 计算机。
  6. 按 F5 键运行这段代码。
  7. 注释掉下面一行以解决上述问题:
    da1.Update(custDS, "Customers")
这个方法很有效,因为 CommandBuilderRowUpdating 事件挂钩到了 DataAdapter("da1")上,这样,它就知道何时生成命令。当您将命令复制到另一个 DataAdapter("da2")中时,CommandBuilder 就不会再挂钩到其事件中,并且不会更改事件。

变量范围很重要,因为如果"da1"和 SqlCommandBuilder("cb")超出了范围,在进行垃圾回收时,CommandBuilder 会将其命令设置为 Nothing(在 Visual C# 中为 null)。这样,就无法在"da2"中使用这些命令了。由于垃圾回收随时都有可能发生,da2.Update 方法调用可能会引发间歇性的 NullReferenceException 错误。

属性

文章编号: 310366 - 最后修改: 2014年2月24日 - 修订: 1.0
这篇文章中的信息适用于:
  • Microsoft ADO.NET(随 .NET 框架一起提供)
  • Microsoft Visual .NET 2002 标准版
关键字:?
kbnosurvey kbarchive kbsqlclient kbsystemdata kbprb KB310366
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com