c# - DataTable update() 插入重复的新行而不检查它是否存在
问题描述
我正在尝试使用 update() 方法,但它正在将我的数据表数据插入到我的数据库中,而不检查该行是否存在,因此它正在插入重复数据。它也不会删除数据表中不存在的行。如何解决这个问题?我想将我的数据表与服务器表同步。
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'MyDatabaseDataSet11.Vendor_GUI_Test_Data' table. You can move, or remove it, as needed.
this.vendor_GUI_Test_DataTableAdapter.Fill(this.MyDatabaseDataSet11.Vendor_GUI_Test_Data);
// read target table on SQL Server and store in a tabledata var
this.ServerDataTable = this.MyDatabaseDataSet11.Vendor_GUI_Test_Data;
}
插入
private void convertGUIToTableFormat()
{
ServerDataTable.Rows.Clear();
// loop through GUIDataTable rows
for (int i = 0; i < GUIDataTable.Rows.Count; i++)
{
String guiKEY = (String)GUIDataTable.Rows[i][0] + "," + (String)GUIDataTable.Rows[i][8] + "," + (String)GUIDataTable.Rows[i][9];
//Console.WriteLine("guiKey: " + guiKEY);
// loop through every DOW value, make a new row for every true
for(int d = 1; d < 8; d++)
{
if ((bool)GUIDataTable.Rows[i][d] == true)
{
DataRow toInsert = ServerDataTable.NewRow();
toInsert[0] = GUIDataTable.Rows[i][0];
toInsert[1] = d + "";
toInsert[2] = GUIDataTable.Rows[i][8];
toInsert[3] = GUIDataTable.Rows[i][9];
ServerDataTable.Rows.InsertAt(toInsert, 0);
//printDataRow(toInsert);
//Console.WriteLine("---------------");
}
}
}
正在尝试更新
// I got this adapter from datagridview, casting my datatable to their format
CSharpFirstGUIWinForms.MyDatabaseDataSet1.Vendor_GUI_Test_DataDataTable DT = (CSharpFirstGUIWinForms.MyDatabaseDataSet1.Vendor_GUI_Test_DataDataTable)ServerDataTable;
DT.PrimaryKey = new DataColumn[] { DT.Columns["Vendor"], DT.Columns["DOW"], DT.Columns["LeadTime"], DT.Columns["DemandPeriod"] };
this.vendor_GUI_Test_DataTableAdapter.Update(DT);
解决方案
让我们看看发布的代码中发生了什么。
首先这一行:
this.ServerDataTable = this.MyDatabaseDataSet11.Vendor_GUI_Test_Data;
这不是副本,而只是两个变量之间的赋值。分配的一个(ServerDataTable)接收对存储来自数据库的数据的内存区域的“引用”。所以这两个变量“指向”同一个内存区域。无论你对一个人做什么都会影响另一个人看到的东西。
现在看看这一行:
ServerDataTable.Rows.Clear();
呃!为什么?您正在清除从数据库加载的数据所在的内存区域。现在 Datatable 是空的,并且那里没有记录 (DataRow)。
让我们看看循环内部发生了什么
DataRow toInsert = ServerDataTable.NewRow();
创建了一个新的 DataRow,现在每个 DataRow 都有一个名为RowState的属性,当您创建新行时,此属性的默认值为DataRowState.Detached
,但是当您在 DataRow 集合中添加行时
ServerDataTable.Rows.InsertAt(toInsert, 0);
然后DataRow.RowState
属性变为DataRowState.Added
。
此时缺少的信息是当您调用 TableAdapter 时的行为方式Update
。适配器需要构建适当的 INSERT/UPDATE/DELETE sql 命令来更新数据库。用于选择正确 sql 命令的信息是什么?实际上,它会查看该RowState
属性,并发现您的所有行都处于“已添加”状态。因此,它为您的表选择 INSERT 命令,并禁止任何重复的键违规,您将在表中以重复记录结束。
你应该怎么做才能解决问题?那么第一件事是从加载的数据中删除清除内存的行,然后,而不是总是调用,InsertAt
您应该首先查看内存中是否已经有该行。您可以使用DataTable.Select方法执行此操作。此方法需要一个字符串,就像它是 WHERE 语句一样,您应该为表的主键使用一些值
var rows = ServerDataTable.Select("PrimaryKeyFieldName = " + valueToSearchFor);
如果您得到的行数大于零,那么您可以使用返回的第一行并使用您的更改更新现有值,如果没有符合条件的行,那么您可以像现在一样使用 InsertAt。
推荐阅读
- google-cloud-platform - Google Cloud AutoML 对象检测导出 CSV 对象位置
- react-native - 如何在本机反应中将子元素添加到特定元素
- google-cloud-sql - 使用 C# 将 Cloud Run 连接到 Cloud SQL Server 实例
- c# - c# 数学和逻辑二叉树表达式求解器
- swift - Swift:将符合 FloatingPoint 的值转换为 Double
- triggers - Zabbix 比较 4 个不同主机的哈希值
- python - 如何为win10编译一个多模块cythonized项目?
- vaadin-flow - 在 Vaadin Flow 选项卡上设置图标
- http - 搜索结果 Web 结果如何在 vue 的不同组件中发出 2 个依赖的 http 请求
- uitableview - SwiftUI 列表如何更改 UITableView.RowAnimation