2016-05-13 38 views
0

我正在研究一個應用程序,該應用程序在用戶點擊提交按鈕時將數據插入到兩個單獨但相關的表中。ADO.NET DataAdapters - 確保一個表在另一個表之前更新

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

但是,因爲我有一個表的外鍵約束,我已經遇到了困難。我需要先插入一個表(report_summary)的行,因爲外鍵約束,甚至在將一行添加到另一個表(report_details)之前。但是,我還希望在單個事務中處理它們,可能會有一個數據完整性問題,一個插入是成功的,另一個插入失敗。我該如何解決這個問題?

的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),但是從我的理解,訂貨節真正應用時,它是一個需要更新的表。

謝謝!

+0

您是否爲數據集中的這兩個數據表建立了正確的關係? –

回答

0

首先滿足插入的外鍵constants的要求。保留該值並使用外鍵關係執行第二次插入。將這些插入包裝在一個事務中。

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

謝謝,我欣賞它,但不是我正在尋找的答案。我正在使用ADO.NET數據適配器 - 問題是如何在執行另一個表上的插入操作之前確保第一個適配器已完成更新(第一個插入語句已完成)。 – KellyMarchewa

+0

同步運行代碼 - 這是沒有委託或回調。 – sammarcow