使用SQL数据适配器更新和插入行不会更新(仅插入)

时间:2014-01-20 16:22:07

标签: c# sql sqldataadapter

我现在正在玩这个,最终我想将CSV文件读入内存,然后将记录插入SQL数据库。应更新现有记录,添加缺失的记录。但是,不应删除新CSV中不存在的记录。

我一直在玩MSDN库中的示例。我知道SqlDataAdapter可以很快地执行批量更新。

我使用名为TempTestTable的表创建了一个小型模拟应用,其中包含TempTestTableIdAgeName列。我写了这个(基于MSDN Article):

using (SqlConnection connection =
   new SqlConnection("data source=localhost;initial catalog=fishsticks;integrated security=True;MultipleActiveResultSets=True;"))
{
    SqlDataAdapter dataAdpater = new SqlDataAdapter(
      "SELECT temptesttableid, Age, Name FROM TempTestTable",
      connection);

    dataAdpater.UpdateCommand = new SqlCommand(
       "UPDATE TempTestTable SET Age = @Age, Name = @Name " +
       "WHERE TempTestTableId = @TempTestTableId", connection);

    dataAdpater.InsertCommand = new SqlCommand(
       "INSERT INTO TempTestTable (Age, Name) " +
       "VALUES (@Age, @Name)", connection);

    SqlParameter parameter = dataAdpater.UpdateCommand.Parameters.Add(
       "@TempTestTableId", SqlDbType.Int);

    dataAdpater.InsertCommand.Parameters.Add(
      "@Age", SqlDbType.Int, 10, "Age");

    dataAdpater.InsertCommand.Parameters.Add(
      "@Name", SqlDbType.NVarChar, 50, "Name");

    dataAdpater.UpdateCommand.Parameters.Add(
      "@Age", SqlDbType.Int, 10, "Age");

    dataAdpater.UpdateCommand.Parameters.Add(
      "@Name", SqlDbType.NVarChar, 50, "Name");

    parameter.SourceColumn = "TempTestTableId";
    parameter.SourceVersion = DataRowVersion.Original;

    DataTable tempTestTable = new DataTable();

    tempTestTable.Columns.Add("Age");
    tempTestTable.Columns.Add("Name");
    tempTestTable.Columns.Add("TempTestTableId");

    var row1 = tempTestTable.NewRow();

    row1["Age"] = 10;
    row1["Name"] = "Smith";
    row1["TempTestTableId"] = 1;

    var row2 = tempTestTable.NewRow();

    row2["Age"] = 40;
    row2["Name"] = "Jones";
    row2["TempTestTableId"] = 2;

    tempTestTable.Rows.Add(row1);
    tempTestTable.Rows.Add(row2);

    dataAdpater.Update(tempTestTable);

数据库中已有TempTestTableId = 1的记录,因此理论上它会更新该记录,并插入ID为2的新记录。但是,当我运行代码时,它会插入两个项目。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

不,DataAdapter只会查看DataRow的RowState属性。如果Added InsertCommand将被执行,如果它是Modified,则UpdateCommand将被执行。您必须先从数据库中将此行加载到表中。

您可以使用DataTable填充空DataAdapter,并使用SelectCommand填充两个参数。如果表为空,则可以手动添加DataRow,否则可以使用更新的值(如果有)修改行并调用dataAdpater.Update(tempTestTable)

这是一个例子(未经测试):

SqlDataAdapter dataAdpater = new SqlDataAdapter(
  "SELECT temptesttableid, Age, Name FROM TempTestTable WHERE Name = @Name",
  connection);

DataTable testTable = new DataTable();
// note that you should use an available csv-parser instead
foreach (string line in File.ReadAllLines(path))
{ 
    string[] columns = line.Split(new char[]{'\t'}, StringSplitOptions.None);
    if(columns.Length >= 2)
    {
        string name = columns[0].Trim();
        string ageStr = columns[1].Trim();
        int age;
        if (int.TryParse(ageStr, out age))
        {
            dataAdpater.SelectCommand.Parameters.AddWithValue("@Name", name);
            int rowsAdded = dataAdpater.Fill(testTable);
            if (rowsAdded == 0)
            {
                testTable.Rows.Add(name, age);
            }
            else
            {
                // update values?
            }
        }
    }
}
dataAdpater.Update(testTable);