[ADO.NET] AcceptChangesすると、DataAdapter経由でDBが更新されない
- 2010 6/30
- 投稿者 : flied_onion
AcceptChangesすると、DataAdapter経由でDBが更新されません。
下のコメントをとると、DataRowVersionがNoChangeになるため。
// dr.AcceptChanges();
sda.Update(ds,"Table_1");
タグ : ADO.NET
AcceptChangesすると、DataAdapter経由でDBが更新されません。
下のコメントをとると、DataRowVersionがNoChangeになるため。
// dr.AcceptChanges();
sda.Update(ds,"Table_1");
ポイントはmyParam=のとこと、OnRowUpdatedイベント
『DataAdapter.RowUpdated イベント
これまでに説明した方法に関連して DataAdapter.RowUpdated イベントを使用すると、オプティミスティック同時実行制御違反をアプリケーションに通知できます。RowUpdated は、DataSet から Modified 行の更新を行ったときに発生します。これにより、例外発生時の処理、カスタム エラー情報の追加、再試行ロジックの追加などの特別の処理コードを追加できます。RowUpdatedEventArgs オブジェクトは、テーブルの変更行に対する特定の更新コマンドによって影響された行数が設定された RecordsAffected プロパティを返します。オプティミスティック同時実行制御をテストするように更新コマンドを設定した場合は、オプティミスティック同時実行制御違反の発生時に、RecordsAffected プロパティは値 0 を結果として返します。値が 0 なのはレコードが更新されないためです。この場合、例外がスローされます。RowUpdated イベントを使用すると、発生したイベントを処理したり、UpdateStatus.SkipCurrentRow のような RowUpdatedEventArgs.Status 値を設定することで例外を抑止したりできます。RowUpdated イベントの詳細については、「DataAdapter イベントの使用」を参照してください
』
[C#]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"); SqlDataAdapter custDA = new SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers ORDER BY CustomerID", nwindConn); // The Update command checks for optimistic concurrency violations in the WHERE clause. custDA.UpdateCommand = new SqlCommand("UPDATE Customers (CustomerID, CompanyName) VALUES(@CustomerID, @CompanyName) " + "WHERE CustomerID = @oldCustomerID AND CompanyName = @oldCompanyName", nwindConn); custDA.UpdateCommand.Parameters.Add("@CustomerID", SqlDbType.NChar, 5, "CustomerID"); custDA.UpdateCommand.Parameters.Add("@CompanyName", SqlDbType.NVarChar, 30, "CompanyName"); // Pass the original values to the WHERE clause parameters. SqlParameter myParm; myParm = custDA.UpdateCommand.Parameters.Add("@oldCustomerID", SqlDbType.NChar, 5, "CustomerID"); myParm.SourceVersion = DataRowVersion.Original; myParm = custDA.UpdateCommand.Parameters.Add("@oldCompanyName", SqlDbType.NVarChar, 30, "CompanyName"); myParm.SourceVersion = DataRowVersion.Original; // Add the RowUpdated event handler. custDA.RowUpdated += new SqlRowUpdatedEventHandler(OnRowUpdated); DataSet custDS = new DataSet(); custDA.Fill(custDS, "Customers"); // Modify the DataSet contents. custDA.Update(custDS, "Customers"); foreach (DataRow myRow in custDS.Tables["Customers"].Rows) { if (myRow.HasErrors) Console.WriteLine(myRow[0] + "\n" + myRow.RowError); } protected static void OnRowUpdated(object sender, SqlRowUpdatedEventArgs args) { if (args.RecordsAffected == 0) { args.Row.RowError = "Optimistic Concurrency Violation Encountered"; args.Status = UpdateStatus.SkipCurrentRow; } } |
seeAlso:http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/cpguide/html/cpconoptimisticconcurrency.asp
note:UpdateCommand Original ADO.NET でGoogle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
namespace DataSetUpdateTest { class Program { static void Main(string[] args) { string response; DataSet ds = new System.Data.DataSet(); DataRow dr; DataSet newDs; DataRow[] rowsInError; DataTable newDt; DataColumn newCol; int i; SqlConnection sc = new SqlConnection(); sc.ConnectionString = "Data Source=PD3GCOT\\SQLEXPRESS;User ID=sa;Password=sa;" + "Initial Catalog=mydb;"; SqlDataAdapter sda = new SqlDataAdapter("Select * from Table_1;",sc); SqlCommandBuilder cb = new SqlCommandBuilder(sda); sc.Open(); sda.MissingSchemaAction = MissingSchemaAction.AddWithKey; sda.Fill(ds, "Table_1"); /* ds.EnforceConstraints = true; ds.SchemaSerializationMode = SchemaSerializationMode.IncludeSchema; ds.WriteXmlSchema("c:\\file.xsd"); */ ds.Tables["Table_1"].Rows[0].Delete(); DataRow delRow; if (ds.HasChanges(DataRowState.Deleted)) { newDs = ds.GetChanges(DataRowState.Deleted); if (!newDs.HasErrors) { delRow = newDs.Tables["Table_1"].Rows[0]; dr = ds.Tables["Table_1"].Rows[0]; try { // the following line generates the exception Console.WriteLine(delRow[0]); } catch (Exception e) { Console.WriteLine("01:" + e.Message); } try { Console.WriteLine(delRow[0, DataRowVersion.Original]); } catch (Exception e) { Console.WriteLine("02:" + e.Message); } try { Console.WriteLine(dr[0, DataRowVersion.Original]); } catch (Exception e) { Console.WriteLine("03:" + e.Message); } // dr.AcceptChanges(); //sda.Update(ds,"Table_1"); } else { Console.WriteLine("newDS has Error"); } } else { Console.WriteLine("newDS has no changes"); } if (sc.State == ConnectionState.Open) sc.Close(); sc = null; Console.WriteLine("Update was processed successfulle?"); Console.ReadLine(); } } } |
天文学的な数値を変換しないかぎりはなくてもよさそう。
やるならtypeof(string)で中間キャストするよりも、
typeof(byte[])のほうがいいんじゃないかとも思われる。
typeof(string)の場合、Oracle DATE型の場合に時刻が失われるという事象が発生。
http://otndnld.oracle.co.jp/document/products/oracle10g/101/doc_v6/win.101/B15519-01/featSafeType.htm
http://msdn2.microsoft.com/ja-jp/library/kbbwt18a.aspx
DataAdapter によるバッチ更新の実行
以前のバージョンの ADO.NET では、DataSet に格納されている変更内容をデータベースに反映する場合、DataAdapter の Update メソッドを実行して、1 行ずつデータベースを更新していました。このメソッドは、指定された DataTable 内の行を反復処理すると、各 DataRow を調べ、行が変更されたことを確認します。行が変更されている場合、その行の RowState プロパティの値に基づいて、適切な UpdateCommand、InsertCommand、または DeleteCommand のいずれかを呼び出します。各行の更新では、データベースへのネットワーク ラウンドトリップが発生します。
ADO.NET 2.0 では、UpdateBatchSize プロパティが DataAdapter によって公開されます。UpdateBatchSize を正の整数値に設定すると、データベースの更新が指定されたサイズのバッチとして送信されます。たとえば、UpdateBatchSize を 10 に設定すると、10 個の個別のステートメントがグループ化され、単一のバッチとして送信されます。UpdateBatchSize を 0 に設定すると、DataAdapter は、サーバーが処理できる最大のバッチ サイズを使用します。1 に設定すると、バッチ更新が無効になり、1 行ずつ送信されます。
サイズの大きいバッチを実行すると、パフォーマンスが低下する可能性があります。そのため、アプリケーションを実装する前に、バッチの最適なサイズ設定をテストする必要があります。
UpdateBatchSize プロパティの使用
バッチ更新を有効にする場合、DataAdapter の UpdateCommand、InsertCommand および DeleteCommand の UpdatedRowSource プロパティ値を、None または OutputParameters に設定する必要があります。バッチ更新を実行する際、FirstReturnedRecord または Both のコマンドの UpdatedRowSource プロパティ値は、無効になります。
UpdateBatchSize プロパティを使用するプロシージャを次に示します。このプロシージャは、2 つの引数を取ります。1 つは、Production.ProductCategory テーブル内の ProductCategoryID フィールドおよび Name フィールドを表す列を持つ DataSet オブジェクトで、もう 1 つは、バッチ サイズ (バッチ ファイル内の行数) を表す整数です。このコードにより、新しい SqlDataAdapter オブジェクトが作成され、その UpdateCommand、InsertCommand プロパティおよび DeleteCommand プロパティが設定されます。このコードは、DataSet オブジェクトによって行が変更済みになっていることを前提としています。このオブジェクトは、UpdateBatchSize プロパティを設定し、更新を実行します。
{C#}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public static void BatchUpdate(DataTable dataTable,Int32 batchSize) { // Assumes GetConnectionString() returns a valid connection string. string connectionString = GetConnectionString(); // Connect to the AdventureWorks database. using (SqlConnection connection = new SqlConnection(connectionString)) { // Create a SqlDataAdapter. SqlDataAdapter adapter = new SqlDataAdapter(); // Set the UPDATE command and parameters. adapter.UpdateCommand = new SqlCommand( "UPDATE Production.ProductCategory SET " + "Name=@Name WHERE ProductCategoryID=@ProdCatID;", connection); adapter.UpdateCommand.Parameters.Add("@Name", SqlDbType.NVarChar, 50, "Name"); adapter.UpdateCommand.Parameters.Add("@ProdCatID", SqlDbType.Int, 4, "ProductCategoryID"); adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None; // Set the INSERT command and parameter. adapter.InsertCommand = new SqlCommand( "INSERT INTO Production.ProductCategory (Name) VALUES (@Name);", connection); adapter.InsertCommand.Parameters.Add("@Name", SqlDbType.NVarChar, 50, "Name"); adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None; // Set the DELETE command and parameter. adapter.DeleteCommand = new SqlCommand( "DELETE FROM Production.ProductCategory " + "WHERE ProductCategoryID=@ProdCatID;", connection); adapter.DeleteCommand.Parameters.Add("@ProdCatID", SqlDbType.Int, 4, "ProductCategoryID"); adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None; // Set the batch size. adapter.UpdateBatchSize = batchSize; // Execute the update. adapter.Update(dataTable); } } |
過去のメモを登録していくつもりがなかなか登録に手間取り古い情報ばかりになってしまっていますのでご利用の際はご注意を
最近のコメント