2016-10-07 1 views
0

Ich bin in der Lage SqlBulkCopy zu tun, wenn keine Abhängigkeit von der Tabelle dort unten mit dem Code ist:Wie kann ich SqlBulkCopy ausführen, wenn eine Abhängigkeit in der Tabelle besteht?

//TableData and FieldData have column info in memory. 
using (SqlConnection connection = new SqlConnection(@"Data Source=WLO1;Initial Catalog=GenTest2;Integrated Security=True")) 
     { 

      connection.Open(); 
      foreach (string tableName in tablesInOrderToProcess) 
      { 
       if (tableDataList.ContainsKey(tableName)) 
       { 
        TableData td = tableDataList[tableName]; 

        SqlBulkCopy copy = new SqlBulkCopy(connection); 
        copy.BatchSize = 10000; 
        copy.DestinationTableName = tableName; 

        System.Data.DataTable dt = new DataTable(); 
        foreach (FieldData fd in td.FieldList.Values) 
        { 
         string fieldName = fd.Name; 
         string fieldDataType = fd.DataType; 
         string fieldSize = fd.Size.ToString(); ; 
         string fieldConstant = fd.constantValue; 
         string fieldAverage = fd.averageSize; 
         string fieldPickList = fd.pickList; 
         copy.ColumnMappings.Add(fieldName, fieldName); 
         switch (fieldDataType) 
         { 
          case "char": 
           { 
            dt.Columns.Add(fieldName, System.Type.GetType("System.String")); 
           } 
           break; 
          case "nvarchar": 
           { 
            dt.Columns.Add(fieldName, System.Type.GetType("System.String")); 
           } 
           break; 
          case "number": 
           { 
            if (fd.Size == 10) 
             dt.Columns.Add(fieldName, System.Type.GetType("System.Int64")); 
            else 
             dt.Columns.Add(fieldName, System.Type.GetType("System.Int32")); 
           } 
           break; 
          default: 
           { 
            dt.Columns.Add(fieldName); 
           } 
           break; 
         } 
        } 
        for (int i = 0; i < int.Parse(td.NumRows); i++) 
        { 
         System.Data.DataRow r = dt.NewRow(); 
         foreach (FieldData fd in td.FieldList.Values) 
         { 
          string fieldName = fd.Name; 
          string fieldDataType = fd.DataType; 
          string fieldSize = fd.Size.ToString(); ; 
          string fieldConstant = fd.constantValue; 
          string fieldAverage = fd.averageSize; 
          string fieldPickList = fd.pickList; 

          switch (fieldDataType) 
          { 
           case "char": 
            { 
             if (fd.averageSize.Length > 0) 
             { 
              r[fieldName] = GetRandomString(Int32.Parse(fd.averageSize), true); 
             } 
             else 
             { 
              r[fieldName] = fieldConstant; 
             } 
            } 
            break; 
           case "nvarchar": 
            { 
             if (fd.averageSize.Length > 0) 
             { 
              r[fieldName] = GetRandomString(Int32.Parse(fd.averageSize), true); 
             } 
             else 
             { 
              r[fieldName] = fieldConstant; 
             } 
            } 
            break; 
           case "number": 
            { 
             if (fd.Size == 10) 
             { 
              r[fieldName] = i; 
             } 
             else 
             { 
              r[fieldName] = i; 
             } 
            } 
            break; 
           default: 
            { 
             r[fieldName] = fieldConstant; 
            } 
            break; 
          } 

         } 
         dt.Rows.Add(r); 
        } 

        try 
        { 
         copy.WriteToServer(dt); 
        } 
        catch (Exception ex) 
        { 
         MessageBox.Show(ex.Message); 
        } 
       } 
      } 
     } 

Wenn jedoch eine Abhängigkeit besteht, ich bin verwirrt. dependency

1) Sollte ich eine DataTable für jede Tabelle erstellen?

2) Da die Informationen zur Tabellenbeziehung vom Benutzer bereitgestellt und in den Speicher geladen werden, wie kann ich Tabellen binden, ohne Informationen aus dem Schema zu lesen? Oder muss ich die Informationen lesen und den Primärschlüssel von Schema abrufen?

Vielen Dank im Voraus. Ich hoffe, ich habe es deutlich gemacht.

Antwort

4

In solchen Situationen können Sie Ihre Bulk-Copy-Operationen nur in temporäre Tabellen ausführen, ohne dass ein Schlüssel die beiden Objekte verbindet (und genug Metadaten, um die Links später zu erstellen).

Angenommen, Sie haben 3 Tabellen: #item_unit_staging, #shop_order_staging und #shop_order_operation_staging. Sie würden sie mit dem gleichen Schema wie item_unit, shop_order und shop_order_operation mit automatisch generierten Primärschlüsseln erstellen. Sie möchten auch alle Daten hinzufügen, die Sie verwendet haben, um die Daten auf Ihrem lokalen Rechner als "Metadatenspalte" zu verknüpfen. Nehmen wir an, dass wir eine zusätzliche Spalte metadata_id für alle drei Tabellen und parent_id für #shop_order_staging und #shop_order_operation_staging verwendet haben.

Wir fügen dann in unsere 3 Tabellen, unsere Primärschlüssel Spalten gefüllt und unsere Fremdschlüssel Spalten links NULL. Sobald wir die Daten auf dem Server haben, verwenden wir die Metadatenspalten, um die Fremdschlüsselspalten zu füllen.

update #shop_order_staging 
    set parent_item_unit_id = #item_unit_staging.item_unit_id 
    from #shop_order_staging 
    inner join #item_unit_staging on #shop_order_staging.parent_id = #item_unit_staging.metadata_id 

update #shop_order_operation_staging 
    set parent_shop_order_id = #shop_order_staging.shop_order_id 
    from #shop_order_operation_staging 
    inner join #shop_order_staging on #shop_order_operation_staging.parent_id = #shop_order_staging.metadata_id 

Anschließend können Sie die Daten aus den temporären Tabellen in den realen Tabellen kopieren

insert into item_unit 
    select item_unit_id 
     , /*all other columns except [metadata_id]*/ 
    from #item_unit_staging 


insert into shop_order 
    select shop_order_id 
     , parent_item_unit_id 
     , /*all other columns except metadata_id and parent_id*/ 
    from #shop_order_staging 

insert into shop_order_operation 
    select shop_order_operation_id 
     , parent_shop_order_id 
     , /*all other columns except metadata_id and parent_id*/ 
    from #shop_order_operation_staging 
+0

Dank @ Scott Chamberlain. Das ist ein sehr kluger Weg. Ich hatte versucht, überall eine Lösung zu finden. – JackTheRipper

Verwandte Themen