1

自動インクリメント整数である ID と呼ばれる 1 つのフィールドを持つデータベース テーブルがあります。TableAdapter を使用すると、既存の行を読み取って変更したり、新しい行を作成したりできます。

ただし、新しく挿入された行を変更しようとすると、DBConcurrencyException が発生します。

 OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Shift.mdb;Persist Security Info=True");
 ShiftDataSetTableAdapters.ShiftTableAdapter shiftTA = new ShiftDataSetTableAdapters.ShiftTableAdapter();
 shiftTA.Connection = conn;

 ShiftDataSet.ShiftDataTable table = new ShiftDataSet.ShiftDataTable();
 ShiftDataSet.ShiftRow row = table.NewShiftRow();
 row.Name = "life";
 table.Rows.Add(row);
 shiftTA.Update(row); // row.ID == -1
 row.Name = "answer"; // <-- all fine up to here
 shiftTA.Update(row); // DBConcurrencyException: 0 rows affected

別の質問ですが、新しい行を挿入するたびにテーブルを作成する必要がないように、使用できる NewShiftRow() メソッドの静的タイプはありますか。

コードの問題は、最初の Update() 呼び出しの後でも -1 である row.ID に起因すると思います。挿入は成功し、データベース内の行には ID の有効な値があります。

2 番目の Update 呼び出しを続行できるように、その ID を取得するにはどうすればよいですか?

アップデート:

これは、この設定を使用して自動的に実行できたようです。ただし、msdn socialの回答によると、OLEDB ドライバーはこの機能をサポートしていません。

ここからどこへ行けばよいかわからない場合は、oledb 以外のものを使用しますか?

アップデート:

SQLCompact を試してみましたが、同じ制限があることがわかりました。複数のステートメントはサポートされていません。

最後の質問: 挿入された行の値を取得できる単純な (単一ファイル ベースの) データベースはありますか。

4

2 に答える 2

1

このhttp://support.microsoft.com/kb/815629を試してみてください。ただし、サンプル コードは VB.NET にあります。

または、MS Access で複数行のクエリが受け入れられ、最後の ID を取得するための関数/変数が組み込まれている場合は、これを使用します (データベースは SQLite ですが):とにかく、これらの数行のコードでこの「同時実行違反」が発生する理由を確認してください。 ??? 同時実行違反: UpdateCommand は予想される 1 レコードのうち 0 に影響を与えました。関数をグーグルで検索してみてください

[編集: 私のマシンで動作します。SQL Server Compact はありませんが、マルチステートメントは使用しませんでした]

public Form1()
{
    InitializeComponent();


    var c = Connect();

    var da = new SqlDataAdapter("select emp_id, emp_firstname, emp_lastname from emp where 1 = 0", c);



    var b = new SqlCommandBuilder(da);

    var getIdentity = new SqlCommand("SELECT CAST(@@IDENTITY AS INT)", c);

    da.InsertCommand = b.GetInsertCommand();
    da.UpdateCommand = b.GetUpdateCommand();
    da.DeleteCommand = b.GetDeleteCommand();
    da.RowUpdated += (xsender, xe) =>
    {
        if (xe.Status == UpdateStatus.Continue && xe.StatementType == StatementType.Insert)
        {
            xe.Row["emp_id"] = (int)getIdentity.ExecuteScalar();
        }
    };


    var dt = new DataTable();
    da.Fill(dt);

    var nr = dt.NewRow();
    nr["emp_firstname"] = "john";
    nr["emp_lastname"] = "lennon";


    var nrx = dt.NewRow();
    nrx["emp_firstname"] = "paul";
    nrx["emp_lastname"] = "mccartney";


    dt.Rows.Add(nr);
    dt.Rows.Add(nrx);

    da.Update(dt);

    dt.AcceptChanges();


    nrx["emp_lastname"] = "simon";
    da.Update(dt);

    nr["emp_lastname"] = "valjean";
    da.Update(dt);

}



SqlConnection Connect()
{
    return new SqlConnection(@"data source=.\SQLEXPRESS;Database=Test;uid=sa;pwd=hey");
}
于 2010-05-12T15:36:07.200 に答える
-1

RowId は INSERT ごとにインクリメントする必要があるため、MAX(RowId) を選択しないのはなぜですか? これは可能ですか?

最終的な答えとしては、SQLiteが最適なツールかもしれません。そうだといい!また、独自の .NET データ プロバイダーを備えているため、OLEDB や ODBC プロバイダーは必要ありません。

于 2010-05-12T15:30:12.653 に答える