2014-01-20 29 views
0

我只是在此時玩弄這個,最終我想將CSV文件讀入內存,然後將記錄插入到SQL中數據庫。應該更新現有的記錄,應該添加缺失的記錄。但是,不應刪除新CSV中不存在的記錄。使用SQL數據適配器更新和插入行不會更新(僅插入)

我一直在玩MSDN庫中的例子。我知道SqlDataAdapter可以很快執行批量更新。

我用TempTestTable表創建了一個小模擬應用程序,它有TempTestTableId,AgeName列。我寫這個(基於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

沒有,'DataAdapter'只會看'DataRow'的['RowState'財產(http://msdn.microsoft.com/ EN-US /庫/ system.data.datarowstate(v = vs.110)的.aspx)。如果它是'Added',則會執行'InsertCommand',如果它是'Modified','UpdateCommand'將被執行。您必須首先將該行從數據庫加載到表中。 –

+0

最初我從MSDN中擷取的例子是這樣做的,但我需要從CSV加載,所以我如何從數據庫和CSV中讀取數據呢?是否必須將當前數據庫表讀入adatatable,然後循環遍歷它,並手動檢查每行對我的CSV,更改值或插入新行,並設置RowState,然後提交它? – NibblyPig

+0

您可以用'DataAdapter'和'SelectCommand'填充一個空DataTable,其中包含兩個參數。如果表爲空,則可以手動添加'DataRow',否則可以使用更新後的值(如果有)修改行並調用'dataAdpater.Update(tempTestTable)'。嗯,這聽起來很混亂,你有一個例子嗎?不管 –

回答

3

不,DataAdapter只會查看DataRow的RowState屬性。如果它是AddedInsertCommand將被執行,如果它是ModifiedUpdateCommand將被執行。您必須首先將該行從數據庫加載到表中。

您可以使用DataAdapter和您的SelectCommand填充空的DataTable,其中包括兩個參數。如果表格爲空,則可以手動添加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); 
+0

謝謝,正在努力實現這一點。我想在更新值部分我必須定義一個UpdateCommand並以某種方式執行它。其實我不確定AddWithValue如何在沒有定義AddCommand的情況下工作... – NibblyPig