【问题标题】:BindingSource sees changes, DataTable doesn'tBindingSource 看到变化,DataTable 没有
【发布时间】:2009-11-02 21:19:49
【问题描述】:

我最近从 Java/RMI 切换到 C#/.net,并且正在开发我的第一个项目,使用数据绑定来更新 Oracle 中的记录。在我正在构建的第一个表格中,我有一个车辆记录的详细视图(VIN、年份/品牌/型号、车牌号等)。在写入数据库方面,我做的第一件事是保存更新:

private void btn_saveDesc_Click(object sender, EventArgs e)
{
    bool isSaved = false;
    hJA_VEHICLEBindingSource.EndEdit();
    DataSet1.HJA_VEHICLEDataTable ch =
        (DataSet1.HJA_VEHICLEDataTable)dataSet1.HJA_VEHICLE.GetChanges();
    if (ch == null)
    {
        MessageBox.Show("There are no changes to save.");
    }
    else 
    {
        Service<TVDDataService.IService1>.Use(svcProxy =>
            {
                isSaved = svcProxy.SaveVehicles(ch);
            });
        if (isSaved)
        {
            // update the vehicle in the local dataset 
            var modifiedRows = from row in dataSet1.HJA_VEHICLE
                               where row.RowState == DataRowState.Modified
                               select row;
            foreach (DataRow row in modifiedRows)
            {
                row.Delete();
            }
            dataSet1.HJA_VEHICLE.Merge(ch);
            dataSet1.HJA_VEHICLE.AcceptChanges();
        }
        if(isSaved)
        {
            MessageBox.Show("The record has been saved.");
        }
        else
        {
            MessageBox.Show("The record could not be saved.");
        }
    }
}

一切看起来都不错,所以我继续添加新记录。我做了一个按钮(我在网上看到很多人都说自己制作比使用绑定导航器更好或更好)并将其放入它的处理程序中:

DataRowView drv = (DataRowView)hJA_VEHICLEBindingSource.AddNew();
currVeh_id = nextID(); // generate arbitrary ID for the record
drv["VEH_ID"] = currVeh_id;
drv["GRNTE_ID"] = lastSelectedGranteeID; // just to have an initial value
hJA_VEHICLEBindingSource.Filter = "VEH_ID = " + currVeh_id;

所以(上)我将初始值放入一些必需的列中(VEH_ID 是 PK)。然后我运行应用程序,在文本框中为 VIN 输入一个值,然后保存(与上面的代码相同),这次 GetChanges() 返回 null。

所以我在“添加新”按钮处理程序中尝试了这个,而不是第一件事:

DataSet1.HJA_VEHICLERow newRow =
    (DataSet1.HJA_VEHICLERow)dataSet1.HJA_VEHICLE.NewRow();
currVeh_id = nextID();
newRow.VEH_ID = currVeh_id;
newRow.GRNTE_ID = lastSelectedGranteeID;
dataSet1.HJA_VEHICLE.AddHJA_VEHICLERow(newRow);
hJA_VEHICLEBindingSource.Filter = "VEH_ID = " + currVeh_id;

现在我发生了一件非常有趣的事情。
- 在选择现有记录之前,我可以成功输入并保存任意数量的新记录的数据。如果我移动到现有记录,然后添加新记录,那么当我去保存新记录时,代码中明确设置的值会写入数据库,但输入到 GUI 中的数据不会“占用”新纪录。
- 我可以成功更改任意数量的现有记录,直到输入新记录。如果我添加一个或多个新记录,保存,然后尝试将更改保存到现有记录,则对 GetChanges() 的调用返回 null(同样,显然它不是“看到”通过 GUI 输入的内容)。

因此,在这两种情况下,从旧到新或从新到旧的变化似乎会引入一些条件,使数据表不知道输入到 GUI 中的内容。但是从旧到新只需选择现有记录,而从新到旧更改时,它只会在保存后中断(如果我做了一个新记录然后放弃它而不保存,我可以毫无问题地修改现有记录) .

我将它添加到保存处理程序中,就在实际保存之前(在循环中,因为 ch 是一个数据表,但实际上代码已设置为您必须在继续之前保存或放弃新记录的位置 -因此循环只执行一次):

foreach (DataSet1.HJA_VEHICLERow r in ch)
{
    DataRowView drv = (DataRowView)hJA_VEHICLEBindingSource.Current;
    MessageBox.Show(drv["VIN_ID"].ToString());
    MessageBox.Show(r.VEH_ID + "\n" + r.GRNTE_ID + "\n'"
        + r.VIN_ID + "'");
}

VIN_ID 是此特定文本框绑定到的列(我也尝试在表单上的其他字段中进行此操作,以验证它不仅仅是那个文本框的一些片状)。第一个消息框(来自绑定源的 DataRowView)显示了我在文本框中输入的 vin。第二个消息框(GetChanges() 返回的表中的行)显示了VIN_ID 的空字符串,尽管它具有VEH_IDGRNTE_ID 的正确(通过代码设置)值。如果我使用绑定到该列的组合框为GRNTE_ID 选择不同的值,也会发生同样的事情;数据表中的行仍然具有通过代码设置的值,“不知道”通过 GUI 选择的值。

为什么数据表和绑定源对于同一个字段会有不同的值?为什么只有在用户从现有切换到新的或从新切换到现有之前,数据表才能“看到”通过 GUI 输入的值?

谢谢。


天使: 我在我的服务中这样做:

public bool SaveVehicles(DataSet1.HJA_VEHICLEDataTable vehicles) 
{ 
    bool saved = false; 
    if (vehicles != null && !vehicles.HasErrors) 
    { 
        HJA_VEHICLETableAdapter ta = new HJA_VEHICLETableAdapter(); 
        int result = ta.Update(vehicles); 
        saved = (result > 0); 
    } 
    return saved; 
} 

这是从我原来的帖子的这个块中调用的:

Service<TVDDataService.IService1>.Use(svcProxy => 
{ 
    isSaved = svcProxy.SaveVehicles(ch); 
}); 

约翰内斯:

对 EndEdit() 的调用是保存处理程序中的第二行(靠近我的帖子顶部)。我也应该在其他地方调用它吗?

谢谢。


澄清一下:SaveVehicles 不可能是问题的根源,因为问题出现在 SaveVehicles 被调用之前。 EndEdit() 被调用之后和实际写入数据库之前,什么条件会导致 BindingSource 和 DataTable 之间出现差异?

【问题讨论】:

    标签: c# data-binding bindingsource


    【解决方案1】:

    您必须在使用 EndEdit(); 后更新您的表格适配器;您也可以使用以下 sn-p 更新您的完整数据集:

                this.BindingSource1.EndEdit();
                this.TableAdapter1.Update(this.DataSet1);
    

    希望有帮助...

    【讨论】:

    • 我在这里这样做: public bool SaveVehicles(DataSet1.HJA_VEHICLEDataTable 车辆) { bool saved = false; if (vehicles != null && !vehicles.HasErrors) { HJA_VEHICLETableAdapter ta = new HJA_VEHICLETableAdapter(); int 结果 = ta.Update(车辆);保存=(结果> 0); } 返回已保存;这在我原来的帖子的这个块中被调用:Service.Use(svcProxy => { isSaved = svcProxy.SaveVehicles(ch); });
    • 抱歉,我还在学习 StackOverflow 编辑/发布的工作原理。我会上去把它放在我原来的帖子里,在那里你可以更容易地阅读它。
    • 尝试对 SaveVehicles 方法进行一些中断并获取流程
    • 也许 isSaved 返回 false,无论尝试在 Visual Studio 上使用观察者
    • 在调用 SaveVehicles 之前问题很明显。从 GetChanges() 返回的数据表已经缺少通过 GUI 输入的值。 SaveVehicles 方法保存传递给它的更改数据表中的内容,在有问题的情况下,缺少通过 GUI 输入的值。传递给 SaveVehciles 方法的内容被保存并返回 true。问题是在原始帖子顶部的保存按钮处理程序的第三行中从 GetChanges() 返回的缺失/未更改的值。谢谢 -
    【解决方案2】:

    *如果您也使用 BindingSource: 只需执行一个简单的 BindingSource.EndEdit(),您的 TextBox 数据就会发送到 DataTable。 示例:-

    _bsHeader.EndEdit();
    if (_dsHeader.HasChanges())
    {
    DataTable dsInsert = _dsHeader.GetChanges(DataRowState.Added).Copy();
    _objDal.Insert(dsInsert);
    }
    

    希望这对在这里绊倒的人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      • 2021-08-16
      • 2018-02-17
      • 2015-10-20
      • 2015-04-11
      • 2021-06-25
      相关资源
      最近更新 更多