SqlDataAdapter.Update 直到第二次更新才写入表

     2023-05-08     124

关键词:

【中文标题】SqlDataAdapter.Update 直到第二次更新才写入表【英文标题】:SqlDataAdapter.Update not writing to table until second update 【发布时间】:2014-08-02 01:15:03 【问题描述】:

我有一个用 C# 2010 Express 开发的程序,它的表单由一个 DataGridView 组成,下面有一个单独的单元格编辑字段。选择行(在其左端单击)时,行中的值将复制到编辑字段中。进行了更改,并单击了“记忆交易”按钮。新值出现在 DataGridView 中。如果表单随后关闭并重新打开(处理并重新加载),则显示原始值,而不是新值。显然数据库记录没有更新。

如果重复上述过程,除了在关闭表单之前再次选择记录并再次单击“记忆事务”按钮外,该值将存储在数据库中。当表单关闭然后重新打开时,会出现新值。

显然,所需的行为是在第一次单击“记忆交易”按钮时立即将值存储在数据库中。

以下声明出现在表单类的顶部:

    DataTable _dt;
    SqlDataAdapter _adapter;

方法 load_DataGridView() 如下所示。请注意,适配器的更新、删除和插入查询是通过调用它们各自的 SqlCommandBuilder 的 GetXXXCommand() 方法构建的。调试期间的断点表明这些已正确填充。

    private void load_dataGridView()
    
        DataTable dt = new DataTable();
        _dt = dt;
        SqlConnection dbconn = new SqlConnection(dbq.connectionString);
        dbconn.Open();
        string qstr = @"SELECT transaction_id
    , 0 as pay
    , m.has_splits
    , m.Num
    , m.Type
    , m.last_date
    , m.next_date
    , m.Payee
    , m.Memo
    , m.Tax_Category
    , m.Amount
    , m.Clr
    , m.Initials
    , m.sales_tax_paid
    , m.from_institution_id as FromInstitutionID
    , m.from_institution as FromInstitution
    , m.from_account_id as FromAccountID
    , m.from_account as FromAccount
    , m.from_envelope_id as FromEnvelopeID
    , m.from_envelope as FromEnvelope
    , m.to_institution_id as ToInstitutionID
    , m.to_institution as ToInstitution
    , m.to_account_id as ToAccountID
    , m.to_account as ToAccount
    , m.to_envelope_id as ToEnvelopeID
    , m.to_envelope as ToEnvelope
    , m.frequency
    FROM memorized m
    ";
        SqlDataAdapter adapter = new SqlDataAdapter(qstr,dbconn);
        SqlCommandBuilder scb = new SqlCommandBuilder(adapter);
        adapter.UpdateCommand = new SqlCommandBuilder(adapter).GetUpdateCommand();
        adapter.DeleteCommand = new SqlCommandBuilder(adapter).GetDeleteCommand();
        adapter.InsertCommand = new SqlCommandBuilder(adapter).GetInsertCommand();
        _adapter = adapter;
        _adapter.Fill(_dt);
        build_dgv_columns(Properties.Settings.Default.currentInstitutionId,
        Properties.Settings.Default.currentAccountId);
        memorizedDataGridView.DataSource = _dt;
    

点击Memorize Transaction按钮时调用的代码如下:

    private void bnMemorizeTx_Click(object sender, EventArgs e)
    
        if (_newTx)
        
            _currentTxRow = _dt.Rows.Count;
            _dt.Rows.Add();
            _newTx = false;
        
        else
        
            _currentTxRow = memorizedDataGridView.SelectedRows[0].Index;
        
        populateRowFromFields(memorizedDataGridView.Rows[_currentTxRow]);
        memorizedDataGridView.Refresh();
        memorizedDataGridView.ClearSelection();
        //grid shows new value with no rows selected at this point, row is "dirty"
        try
        
            _adapter.Update(_dt);
        
        catch (SqlException e1)
        
            MessageBox.Show(e1.Message + e1.InnerException, "Error Thrown",MessageBoxButtons.OK);
        
        reset_transaction_fields();
    

从来没有抛出异常。我怀疑将数据从 DataGridView 拉到编辑字段中,然后以某种方式再次将其写回的操作会以某种方式使用 _adapter.Update(_dt) 命令检测行已更改的能力,因此当它被调用时,它不会不更新任何东西。然后在第二次尝试时,当重新选择行(显示新值)但没有进行编辑更改时,它确实有效。不知何故,即使新值出现在网格中,也好像尚未提交更改,必须重新选择该行才能发生这种情况。

populateRowFromFields 方法如下,使用单元格索引的列名引用将编辑字段中的值写回行中的单元格值:

            private void populateRowFromFields(DataGridViewRow dgvr)
    
        dgvr.Cells["Num"].Value = tbRefNum.Text;
        dgvr.Cells["Type"].Value = cbType.GetItemText(cbType.SelectedItem);
        dgvr.Cells["last_date"].Value = dtpLastPaid.Value.ToShortDateString();
        dgvr.Cells["next_date"].Value = dtpNextPay.Value.ToShortDateString();
        dgvr.Cells["Payee"].Value = tbPayee.Text;
        dgvr.Cells["Amount"].Value = tbAmount.Text;
        dgvr.Cells["FromInstitutionID"].Value = cbFromInst.GetItemText(cbFromInst.SelectedValue); // fromInst
        dgvr.Cells["FromInstitution"].Value = cbFromInst.GetItemText(cbFromInst.SelectedItem); // fromAcct
        dgvr.Cells["FromAccountID"].Value = cbFromAcct.GetItemText(cbFromAcct.SelectedValue); // fromEnv
        dgvr.Cells["FromAccount"].Value = cbFromAcct.GetItemText(cbFromAcct.SelectedItem); // fromInst
        dgvr.Cells["FromEnvelopeID"].Value = cbFromEnv.GetItemText(cbFromEnv.SelectedValue); // fromAcct
        dgvr.Cells["FromEnvelope"].Value = cbFromEnv.GetItemText(cbFromEnv.SelectedItem); // fromEnv
        if ((cbType.GetItemText(cbType.SelectedItem) == "+iTx") || (cbType.GetItemText(cbType.SelectedItem) == "-iTx") || (cbType.GetItemText(cbType.SelectedItem) == "+eTx") || (cbType.GetItemText(cbType.SelectedItem) == "-eTx")) 
        
            dgvr.Cells["ToInstitutionID"].Value = cbToInst.GetItemText(cbToInst.SelectedValue); // toInst
            dgvr.Cells["ToInstitution"].Value = cbToInst.GetItemText(cbToInst.SelectedItem); // toInst
            dgvr.Cells["ToAccountID"].Value = cbToAcct.GetItemText(cbToAcct.SelectedValue); // toAcct
            dgvr.Cells["ToAccount"].Value = cbToAcct.GetItemText(cbToAcct.SelectedItem); // toAcct
            dgvr.Cells["ToEnvelopeID"].Value = cbToEnv.GetItemText(cbToEnv.SelectedValue); // toEnv
            dgvr.Cells["ToEnvelope"].Value = cbToEnv.GetItemText(cbToEnv.SelectedItem); // toEnv
            hideTxToFields();
        
        dgvr.Cells["Memo"].Value = tbMemo.Text;
        dgvr.Cells["Tax_Category"].Value = cbTaxCategory.GetItemText(cbTaxCategory.SelectedItem); // taxCategory
        dgvr.Cells["sales_tax_paid"].Value = cbSalesTaxPaid.GetItemText(cbSalesTaxPaid.SelectedItem); // salesTaxPaid
        dgvr.Cells["Clr"].Value = "U";
        dgvr.Cells["Initials"].Value = cbBy.GetItemText(cbBy.SelectedItem); // by
        dgvr.Cells["frequency"].Value = cbFrequency.GetItemText(cbFrequency.SelectedItem); // frequency
    

帮助!这让我发疯了!

【问题讨论】:

我建议您以错误的方式解决此问题。您应该填充DataTable,将其绑定到BindingSource,然后将其绑定到您的DataGridView 和您的编辑字段。当用户在网格中选择一行时,其字段将自动显示在编辑字段中;无需代码。提交更新时,在编辑字段中所做的任何更改都将自动推送回网格。当您导航到另一条记录时,这将自动发生,但您也可以在保存之前调用 BindingSource 上的 EndEdit 强制它。 有道理——我完全赞成“不需要代码”。但我不确定将编辑字段(全部 24 个)绑定到 BindingSource 的代码是什么样的。你能举一个简短的例子吗? TIA 另外,当我说 _adapter.Fill(_dt); 时,我不是在填充数据表吗?和 memorizedDataGridView.DataSource = _dt;? (您必须在代码窗口中向下滚动才能看到这些行) 是的,Fill 调用是您填充DataTable 的方式,但我想在我的描述中包含所有必需的步骤。我将发布一个代码示例作为答案。 谢谢,j,给我一天的时间试试这个,然后我会发布结果并标记为解决方案。更清晰。 【参考方案1】:

最简单的选择是通过BindingSource 对网格和编辑控件使用数据绑定,例如

private SqlConnection connection;
private SqlDataAdapter adapter;
private SqlCommandBuilder builder;
private DataTable table;

private void Form1_Load(object sender, EventArgs e)

    connection = new SqlConnection("connection string here");
    adapter = new SqlDataAdapter("SELECT * FROM Person", connection);
    builder = new SqlCommandBuilder(adapter);
    table = new DataTable();

    adapter.Fill(table);
    bindingSource1.DataSource = table;
    dataGridView1.DataSource = bindingSource1;
    givenNameTextBox.DataBindings.Add("Text", bindingSource1, "GivenName");
    familyNameTextBox.DataBindings.Add("Text", bindingSource1, "FamilyName");


private void addButton_Click(object sender, EventArgs e)

    bindingSource1.AddNew();


private void deleteButton_Click(object sender, EventArgs e)

    bindingSource1.RemoveCurrent();


private void saveButton_Click(object sender, EventArgs e)

    bindingSource1.EndEdit();
    adapter.Update(table);

【讨论】:

再次感谢,j,一旦我对 C# 进行了必要的转换(没什么大不了的,谢天谢地,VB 和 C# 在这种情况下非常接近,但可能会让新手感到困惑),它工作得很好.我有这个古铜色以备将来参考! :-) 非常抱歉发布 VB 代码。我大部分时间都在回答 VB 问题,却忘了这次我不是。即使您已经为自己完成了,我也会替换代码以防其他人遇到类似问题。

SqlDataAdapter.update() 不更新数据库

】SqlDataAdapter.update()不更新数据库【英文标题】:SqlDataAdapter.update()notupdatingdatabase【发布时间】:2015-04-0704:22:47【问题描述】:我正在使用SqlDataAdapter在PostLikes表中搜索(PostId,UserId),如果找到该行,我正在使用SqlCommandBuilder.GetDelet... 查看详情

C# SqlDataAdapter.Update()

】C#SqlDataAdapter.Update()【英文标题】:【发布时间】:2010-07-1208:39:42【问题描述】:我要疯了。我做了ff:创建数据表。通过SqlDataAdapter从SQL数据库填充它。通过datagridview编辑数据表。调用sqldataadapter.update但更改不会持久化到数据... 查看详情

SqlDataAdapter.Update 未更新

】SqlDataAdapter.Update未更新【英文标题】:SqlDataAdapter.Updatenotupdating【发布时间】:2015-10-2119:34:29【问题描述】:(我应该说我对vb.net相当陌生)我在覆盖我的数据库中的条目时遇到问题。我认为问题在于SqlDataAdapter.Update没有用我... 查看详情

在 SqlDataAdapter.Update() 中获取错误消息

】在SqlDataAdapter.Update()中获取错误消息【英文标题】:GettingerrormessageinSqlDataAdapter.Update()【发布时间】:2016-07-1419:43:38【问题描述】:我有一个数据库表(在本例中为空)createtablewords(idintnotnull,wordnvarchar(50)notnull)还有一个DataGridVie... 查看详情

200万条记录的SqlDataAdapter.Update()速度极慢

】200万条记录的SqlDataAdapter.Update()速度极慢【英文标题】:SqlDataAdapter.Update()of2millionrecordsisextremelyslow【发布时间】:2019-04-3009:22:51【问题描述】:我有一个客户希望每天将他的子客户价格工具(超过2.000.000条记录)导入SQLServer数... 查看详情

使用 SqlDataAdapter.Update 方法时复制表行

】使用SqlDataAdapter.Update方法时复制表行【英文标题】:DuplicatingtablerowswhenusingSqlDataAdapter.UpdateMethod【发布时间】:2013-11-0403:08:40【问题描述】:在我的项目中,我有表格“产品”。IDNamePrice------------------1xyz1002abc2003pqr300在我的c#代... 查看详情

当 RowState = Modified 时 SQLDataAdapter.Update() 不更新

】当RowState=Modified时SQLDataAdapter.Update()不更新【英文标题】:SQLDataAdapter.Update()notUpdatingwhenRowState=Modified【发布时间】:2018-05-1516:41:39【问题描述】:我正在尝试设置一个程序,当用户更新项目描述时,将在保存表单时更新数据库... 查看详情

SqlDataAdapter.Update(dataset) 方法插入新行但不更新现有行

】SqlDataAdapter.Update(dataset)方法插入新行但不更新现有行【英文标题】:SqlDataAdapter.Update(dataset)methodinsertsnewrowsbutdoesnotupdatesexistingrows【发布时间】:2014-06-0114:56:49【问题描述】:我正在创建具有DataGrigView来呈现表格的winform应用程... 查看详情

SqlDataAdapter.Update(数据表)不工作(不更新数据库)

】SqlDataAdapter.Update(数据表)不工作(不更新数据库)【英文标题】:SqlDataAdapter.Update(datatable)isnotworking(notupdatingthedatabase)【发布时间】:2016-04-0516:34:30【问题描述】:我有下面的代码,我试图从Windows应用程序中所做的c#网格视... 查看详情

如果我将列值“更改”为已经存在的值,会调用 UPDATE 吗?

...需要额外的逻辑来避免对我的SQL数据库的无用调用,或者SqlDataAdapter.Update()是否会做正确的事情。如果我有这个代码:SqlCon 查看详情

如何继续删除第一个值,直到向量的总和小于 20?

】如何继续删除第一个值,直到向量的总和小于20?【英文标题】:Howtokeepdroppingthefirstvalue,untilthesumofthevectorislessthan20?【发布时间】:2019-06-1005:53:41【问题描述】:我正在寻找一个函数,它接受一个向量并不断删除第一个值,直... 查看详情

PHP删除第一行文件直到达到阈值[重复]

】PHP删除第一行文件直到达到阈值[重复]【英文标题】:PHPdeletefirstrowoffiletillthresholdisreached[duplicate]【发布时间】:2020-05-2322:49:33【问题描述】:我想将我的日志文件缩减到7KB。但是修剪只运行一次,文件大小也不会更新。代码... 查看详情

在第一个空格之后直到字符串结尾

】在第一个空格之后直到字符串结尾【英文标题】:gettillendofstringafterfirstspace【发布时间】:2017-07-1811:15:17【问题描述】:当我尝试使用split_part时,我需要按如下方式拆分字符串selectsplit_part(\'8HAMPSHIRERD\',\'\',2)预期输出:HAMPSHIRE... 查看详情

按值对行进行分组,直到它更改(分组包括第一个更改的值)

】按值对行进行分组,直到它更改(分组包括第一个更改的值)【英文标题】:Groupingrowsbyvalueuntilitchanges(groupingincludesthefirstchangedvalue)【发布时间】:2020-10-1307:48:48【问题描述】:我有以下数据集:行按start_time字段升序排序,我... 查看详情

如何获取子字符串直到第 2 次出现分隔符

】如何获取子字符串直到第2次出现分隔符【英文标题】:Howtogetsubstringtill2ndoccurenceofdelimiter【发布时间】:2020-02-2514:05:26【问题描述】:我正在尝试获取子字符串,直到第2次出现分隔符,但有些无法正常工作。我关注了几个***... 查看详情

如何修复 MapView 放大位置直到出现第二次视图

】如何修复MapView放大位置直到出现第二次视图【英文标题】:HowtofixMapViewzoomintolocationuntilasecondtimeviewappears【发布时间】:2013-06-0423:58:47【问题描述】:我有一个应用程序可以加载带有3个选项卡的tabbarcontroller。其中之一是地图... 查看详情

Erlang 套接字直到第二个 setopts active,once 才接收

】Erlang套接字直到第二个setoptsactive,once才接收【英文标题】:Erlangsocketdoesn\'treceiveuntilthesecondsetoptsactive,onceErlang套接字直到第二个setoptsactive,once才接收【发布时间】:2011-12-1107:24:08【问题描述】:首先我要道歉,我提供了这么多... 查看详情

SQL 查询:查找连接的联系人直到第三度深度

】SQL查询:查找连接的联系人直到第三度深度【英文标题】:SQLquery:Findingconnectedcontactsuntilthirddegreeofdepth【发布时间】:2016-03-2214:50:04【问题描述】:我使用的是PostgreSQL8.2.15(GreenplumDatabase4.3.3.1build1),这意味着不支持使用WITHRE... 查看详情