1

我最近从 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_IDGRNTE_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 之间的差异?

4

2 回答 2

1

使用 EndEdit(); 后,您必须更新表格适配器;您也可以使用以下代码段更新您的完整数据集:

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

希望有帮助...

于 2009-11-02T21:27:57.383 回答
0

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

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

希望这可以帮助任何在这里绊倒的人。

于 2013-03-13T08:13:28.993 回答