2016-05-13 1 views
0

ユーザーが送信ボタンを押したときに、別の2つの関連テーブルにデータを挿入するアプリケーションで作業しています。ADO.NET DataAdapters - あるテーブルが別のテーブルに更新されていることを確認する

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_details_report" 

しかし、1つのテーブルに外部キーの制約があるため、問題が発生しています。外部キーの制約のために、1つのテーブル(report_summary)の行が最初に挿入される必要があります。しかし、私はまた、それらが単一のトランザクションで処理されることを望みます。挿入が成功し、もう一方が失敗するといういくつかのデータ整合性の問題があるかもしれません。どうすれば解決できますか?

T-SQL

CREATE TABLE [dbo].[report_summary] (
    [report_id] INT NOT NULL, 
    [inspector] INT NOT NULL, 
    [employee] INT NOT NULL, 
    [room]  INT NOT NULL, 
    [date]  DATE NOT NULL, 
    [score]  INT NOT NULL, 
    [locationID] INT NOT NULL, 
    PRIMARY KEY CLUSTERED ([report_id] ASC), 
    CONSTRAINT [FK_report_summary_locations] FOREIGN KEY ([locationID]) REFERENCES [dbo].[locations] ([locID]) 
); 



CREATE TABLE [dbo].[report_details] (
    [reportID] INT NOT NULL, 
    [itemID] INT NOT NULL, 
    [points] INT NOT NULL, 
    [comments] NTEXT NULL, 
    PRIMARY KEY CLUSTERED ([itemID] ASC, [reportID] ASC), 
    CONSTRAINT [FK_details_items] FOREIGN KEY ([itemID]) REFERENCES [dbo].[items] ([itemID]), 
    CONSTRAINT [FK_details_report] FOREIGN KEY ([reportID]) REFERENCES [dbo].[report_summary] ([report_id]) 
); 

と私のC#

private void submitData(object sender, RoutedEventArgs e) 
{ 
    SqlTransaction tran = con.BeginTransaction(); 

    reportAdapter.InsertCommand.Transaction = tran; 
    SqlCommand query = new SqlCommand("SELECT report_id FROM dbo.report_summary ORDER by report_id DESC", con); 
    query.Transaction = tran; 
    int nextReportID; 
    if (query.ExecuteScalar() != null) 
    { 
     nextReportID = (int)query.ExecuteScalar() + 1; 
    } 
    else 
    { 
     nextReportID = 1; 
    } 

    detailsAdapter.InsertCommand.Transaction = tran; 

    DataRow reportRow = ds.Tables["Reports"].NewRow(); 
    reportRow["report_id"] = nextReportID; 
    DataRowView inspectorSelection = (DataRowView)inspectorBox.SelectedItem; 
    reportRow["inspector"] = Int16.Parse(inspectorSelection["empID"].ToString()); 

    DataRowView empSelection = (DataRowView)employeeBox.SelectedItem; 
    reportRow["employee"] = Int16.Parse(inspectorSelection["empID"].ToString()); 

    DataRowView locationSelection = (DataRowView)locationComboBox.SelectedItem; 
    reportRow["locationID"] = Int16.Parse(locationSelection["locID"].ToString()); 
    reportRow["room"] = Int16.Parse(roomTextBox.Text); 
    reportRow["date"] = DateTime.Now.ToString("yyy-MM-dd"); 
    reportRow["score"] = currentPoints; 
    ds.Tables["Reports"].Rows.Add(reportRow); 

    // update report_details dataset 
    foreach (DataRow row in ds.Tables["Grid"].Rows) 
    { 
     DataRow reportDetailsRow = ds.Tables["Details"].NewRow(); 

     reportDetailsRow["reportID"] = nextReportID; 
     reportDetailsRow["itemID"] = row["ID"]; 
     reportDetailsRow["points"] = row["Current"]; 
     reportDetailsRow["comments"] = row["Comments"]; 

     ds.Tables["Details"].Rows.Add(reportDetailsRow); 

    } 

    // update tables as single transaction 
    try 
    { 

     reportAdapter.Update(ds, "Reports"); 
     detailsAdapter.Update(ds, "Details"); 
     tran.Commit(); 
     MessageBox.Show("Data Inserted"); 
    } 
    catch (SqlException sqlEr) 
    { 
     MessageBox.Show(sqlEr.Message); 
     tran.Rollback(); 
    } 
} 

のいくつかの私は、マイクロソフト(https://msdn.microsoft.com/en-us/library/33y2221y(v=vs.110).aspx)によって、この記事を参照しますが、それがあったとき、私の理解から、注文セクションは、実際に適用されます更新が必要な1つのテーブル

ありがとうございます!

+0

データセット内の2つのデータセットに対して正しく関係を設定していますか? –

答えて

0

まず、外部キー定数の要件を挿入します。その値を保持し、外部キー関係を使用して2番目の挿入を実行します。これらの挿入をトランザクションにラップします。

begin transaction 
    INSERT INTO TableA (Id) VALUES (1) 
    INSERT INTO TableB (Id, TableAID) VALUES (newid(), 1) 
commit transaction 
+0

ありがとう、私はそれを感謝しますが、かなり私が探していた答えはありません。私はADO.NETのデータアダプタを使用しています - 質問は、最初のアダプタの更新が完了したことを確認する方法です(最初のINSERT文は完了しています)。 – KellyMarchewa

+0

は、デリゲートやコールバックのないコードを同期して実行します。 – sammarcow