【问题标题】:How to Insert Into SQL Server Using BindingSource如何使用 BindingSource 插入 SQL Server
【发布时间】:2021-01-19 22:07:57
【问题描述】:

我想在 Windows 窗体和 VB 中使用 BindingSource 从 SQL Server 插入数据库。

现在我有一个 DataTable,它的 DataTableAdapter 处于“详细信息”模式,还有一堆 TextBox(和其他控件,但这不是问题),它们的 Text 属性绑定到我的 BindingSource。

如果我填充 TableAdapter XDataTableAdapter.Fill(XDataSet.XTable) 那些 TextBoxs 从第一个条目接收数据,并且 BindingSource 具有来自 db 的每一行和每个列值,因此 BindingSource 和适配器工作。

我不想修改现有条目,而是插入一个新条目,其内容与各种文本框中链接的内容相同。

我被告知我应该使用XBindingSource.AddNew(),最后,一旦我确定了文本框中的数据XDataTableAdapter.Update(XDataSet.XTable)

问题是,在我执行 AddNew 之前,我的 BindingSource 可以读取正在写入的内容。但是一旦我到达 AddNew,BindingSource 的计数就会增加 1,但其当前行的 Items 是空的,无论 TextBox 的内容如何。

所以问题是,在 BindingSource.AddNew 之后,来自 db 的行正确包含其值,但当前的新行将它们设为空,而无需从文本框的 bindingsources 中读取。是否有任何指令要 BindingSource 执行以便它知道新行应该读取文本框?

所以当我到达更新指令时,新行是空的,所以它不会改变任何东西。

我的问题是,我如何告诉 BindingSource 新的当前行是文本框中正在写入的内容。

我只是想直接从控件绑定中插入我的数据库,而不必手动链接每一个。

【问题讨论】:

  • 不确定您所描述的场景,但您是否曾致电[BindingSource].EndEdit()?或Validate().
  • 我没有调用 EndEdit() 因为我不打算编辑用户编写的内容,并且在允许单击按钮之前通过正则表达式执行验证,所以我不使用 Validate( ) 都没有
  • 您应该在输入新数据之前致电AddNew。如果TextBoxes 绑定到BindingSource,那么调用AddNew 应该创建一个新的DataRow,其中RowStateDetached,并且该行应该是您在控制中看到的。然后用户将数据输入该行。您可以通过这种方式添加和编辑任意数量的行。当需要保存时,您在表单上调用Validate,在BindingSource 上调用EndEdit,以确保最后一个挂起的编辑已推送到数据源,然后在适配器上调用Update
  • 请注意,如果您在调用AddNew 之后在BindingSource 上调用CancelEdit,则Detached DataRow 将被丢弃,而不会实际添加到DataTableAddNew 将在 DataTable 上调用 NewRowEndEdit 将调用 Rows.Add

标签: sql-server vb.net winforms bindingsource


【解决方案1】:

如果可以的话,我会纠正一些误解;希望它能帮助您了解发生了什么:

现在我有一个 DataTable,它的 DataTableAdapter 处于“详细信息”模式,还有一堆 TextBox(和其他控件,但这不是问题),它们的 Text 属性绑定到我的 BindingSource。

您有一个 TableAdapter - 当您使用这种访​​问数据库的方法时 VS 为您生成的事物类型的通用名称。请务必将它们称为 TableAdapter,因为这是我们对它们的了解,并且它们与 DataAdapter 不同,后者是访问数据库的更基本的东西。如果您将其称为 DataTableAdapter,人们可能会对您的意思感到困惑

TableAdapter 没有“详细信息”模式。 “详细信息”是指您在“数据源”窗口中所做的事情 - 您从 datagrid 更改为 details,然后将代表 数据表 的节点拖到表单和一堆文本框等出现了,还有一个表格适配器、数据集、绑定源、绑定导航器,也许还有一个表格适配器管理器。此时,您除了运行程序之外别无他法,它将能够保存新数据。 “详细信息”的意思是“创建一堆文本框而不是数据网格”,并且只是数据源窗口的功能

如果我填充 TableAdapter XDataTableAdapter.Fill(XDataSet.XTable) 那些文本框从第一个条目接收数据,并且 BindingSource 具有来自 db 的每一行和每个列值,因此 BindingSource 和适配器工作。

再一次,稍微调整一下术语:您不填充 TableAdapter,TableAdapter 是填充数据表的设备。它填充的数据表位于数据集中。 bindingsource 绑定(连接)到数据表。数据表保存从数据库下载的本地数据的缓存。文本框绑定到绑定源。因为文本框一次只能显示一条记录,所以绑定源会保持对“当前”记录的了解。绑定导航器(工具栏)移动绑定源的当前指针,这会导致文本框更改值。您可以使用文本框更改值或添加新值。这会导致绑定源将更改传输到底层数据表,从而影响它认为是“当前”行的任何行。在某些时候,您将更改的数据表保存回数据库。基础数据表行从未更改(下载时的状态)更改为已修改。这就是 tableadapter 知道运行 SQL UPDATE 查询的方式 - 它查看行的状态

我不想修改现有条目,而是插入一个新条目,其内容与各种文本框中链接的内容相同。我被告知我应该使用 XBindingSource.AddNew() 最后,一旦我确定 TextBoxs XDataTableAdapter.Update(XDataSet.XTable) 中的数据。

您确实可以做到这一点。 bindingnavigator 上有一个+ 按钮可以执行此操作,或者您可以编写一些其他代码在 bindingsource 上调用AddNew()。当您调用 AddNew 时,bindingsource 会创建一个新的数据行,但它不会立即向数据表添加任何内容。当您将 bindingsource 告诉 AddNew 时,它将切换到将其当前指向新项目,所有文本框都变为空白,您可以在其中键入新的详细信息。这些详细信息将进入新的临时行,但请记住,该行还不是基础数据表的一部分

问题是,在我执行 AddNew 之前,我的 BindingSource 可以读取正在写入的内容。但是一旦我到达 AddNew,BindingSource 的计数就会增加 1,但其当前行的 Items 是空的,无论 TextBox 的内容如何。

这不是问题,这是设计使然。这与打开 Word 并编写文档相同 - 它还没有保存在您的硬盘上,它只是在内存中。您需要做一些事情将其提交到硬盘,就像您需要对绑定源做一些事情以使其将新项目提交到底层数据存储(数据表)中一样

要使其提交,您需要执行以下操作:导航到另一条记录,或在绑定源上调用 EndEdit()。此时,它将行添加到基础表中,并且这个新行的 RowState 为已添加 - 这意味着当 tableadapter 运行其更新(实际上应该称为保存)时,它将使用内置的 SQL INSERT 查询来保存排;因为它是添加/新/需要插入到数据库中

所以问题是,在 BindingSource.AddNew 之后,来自 db 的行正确包含其值,但当前的新行将它们设为空,而无需从文本框的 bindingsources 中读取。是否有任何指令要 BindingSource 执行以便它知道新行应该读取文本框?

我认为你做事的顺序不对。您应该 AddNew,然后用新数据填写文本框,然后执行一些操作,例如离开新数据,或点击保存或其他在表单上执行 Validate()/EndEdit() 的按钮/绑定源。新行的提交发生在 bindingsource 的 EndEdit() 上;将行放入表中,但此时仍未将其保存到数据库中。要保存,必须致电tableadapter.Update(theTable)

这可能看起来有点奇怪,但再一次,把它想象成 MS Word。您可以打开一个现有文档,然后您可以对一个新文档执行 Ctrl+N,然后您编写该文档。新文档尚未保存到磁盘。

在 tableadapter 术语中,过程是相同的:您可以下载现有的数据库表,然后可以为新行执行 AddNew,然后编写新行的详细信息。新行尚未保存到数据库中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-28
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多