2016-05-13 10 views
0

Ich arbeite an einer Anwendung, die Daten in zwei separate, aber verknüpfte Tabellen einfügt, wenn ein Benutzer eine Übergabeschaltfläche drückt.ADO.NET DataAdapters - Sicherstellen, dass eine Tabelle ein Update vor einem anderen ist

Da ich jedoch eine Fremdschlüsseleinschränkung auf einem Tisch habe, stößt ich auf Schwierigkeiten. Ich brauche die Zeilen für eine Tabelle (report_summary) wegen der Fremdschlüsseleinschränkungen zuerst eingefügt werden, bevor sogar eine einzelne Zeile zu der anderen Tabelle hinzugefügt wird (report_details). Allerdings möchte ich auch, dass sie in einer einzigen Transaktion behandelt werden, da einige Datenintegritätsprobleme bei einem Insert erfolgreich sein und bei dem anderen fehlschlagen. Wie kann ich das beheben?

Die 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]) 
); 

und einige meiner 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(); 
    } 
} 

ich diesen Artikel von Microsoft verwiesen (https://msdn.microsoft.com/en-us/library/33y2221y(v=vs.110).aspx), aber aus meinem Verständnis angelegte Bestell Abschnitt wirklich, wenn es eine Tabelle, die Updates benötigt.

Danke!

+0

Sind die Beziehungen für diese beiden Datentabellen im Dataset korrekt eingerichtet? –

Antwort

0

Zuerst erfüllen die Anforderungen des Fremdschlüssels constaint mit einem Einsatz. Behalten Sie diesen Wert bei und führen Sie eine zweite Einfügung mithilfe der Fremdschlüsselbeziehung durch. Wickeln Sie diese Einsätze in eine Transaktion ein.

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

Danke, ich schätze es, aber nicht ganz die Antwort, die ich suchte. Ich verwende ADO.NET-Datenadapter - die Frage ist, wie stelle ich sicher, dass der erste Adapter die Aktualisierung abgeschlossen hat (die erste insert-Anweisung wurde abgeschlossen), bevor die Einfügung in einer anderen Tabelle ausgeführt wird. – KellyMarchewa

+0

führen Sie den Code synchron - das ist ohne Delegaten oder Rückrufe. – sammarcow