2016-05-13 82 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