2012-04-04 18 views
0

Frage: Ich benutze die unten Klasse eine CSV-Datei zuSystem.Reflection, wie Feld- und Eigenschaftsposition erhalten?

List<MyCsvFileType>

Dann konvertiere ich die List<MyCsvFileType> auf eine Datentabelle mit

MyConvertTo

serialisiert (auch unten aufgeführt). Das Problem ist jetzt, MyConvertTo ändert die Position der Spalten, was bedeutet, dass alle Eigenschaften nach allen öffentlichen Variablen kommen.

Das Problem, das verursacht, ist, dass ich anschließend SqlBulkCopy verwenden, um die DataTable in eine Datenbanktabelle zu kopieren. Und leider verwendet SqlBulkCopy die Indizes der Spalte anstelle des Spaltennamens für die automatische Zuordnung Datentabelle zu Datenbanktabelle.

Was bedeutet, dass ich nette Fehlermeldungen bekommen, weil es die alphanumerischen AP_FL_CADKey im Schwimmerbereich Feld einzufügen versucht (weil meine Datenbank-Tabellen das gleiche Layout wie die Klasse haben) ...

Gibt es eine Möglichkeit Ich kann die Position der Felder & Eigenschaften in MyConvertTo bekommen? Also muss ich meine Datenbanktabellen (Lose) nicht ändern oder meine eigene Implementierung von BulkCopy schreiben, , weil ich nicht auch die Zuordnung zwischen Datentabelle und Datenbanktabelle manuell festlegen möchte?

Es sollte möglich sein, im schlimmsten Fall durch die durch die Felder Offsets Sortierung ...

Klasse:

[FileHelpers.IgnoreFirst] 
[FileHelpers.IgnoreEmptyLines] 
public class MyCsvFileType 
{ 
    public string FL_CADKey; 
    public string FL_DWG; 
    public string FL_ObjID; 

    public string FL_Area; 

    public double FL_Area_double 
    { 
     get 
     { 
      if (string.IsNullOrEmpty(this.FL_Area)) 
       return 0.0; 
      else 
       return System.Convert.ToDouble(this.FL_Area); 
     } 

    } // End Property PP_Area_double 


    public string AP_FL_CADKey; 


    public System.Guid UID 
    { 

     get 
     { 
      return System.Guid.NewGuid(); 
     } 

    } // End Property UID 
} 

MyConvertTo:

public static DataTable MyConvertTo(dynamic custs) 
{ 
    DataTable dt = MyCreateTable(custs); 

    System.Data.DataRow dr = null; 
    foreach (dynamic cli in custs) 
    { 
     Console.WriteLine(); 

     Type t = cli.GetType(); 

     dr = dt.NewRow(); 

     foreach (System.Reflection.FieldInfo fi in t.GetFields()) 
     { 
      dr[fi.Name] = fi.GetValue(cli); 
     } 

     foreach (System.Reflection.PropertyInfo pi in t.GetProperties()) 
     { 
      dr[pi.Name] = pi.GetValue(cli, null); 
     } 

     dt.Rows.Add(dr); 
    } // Next cli 

    return dt; 
} 



public static DataTable MyCreateTable(dynamic custs) 
    { 
     DataTable table = new DataTable("Table_1"); 

     foreach (dynamic cli in custs) 
     { 
      Console.WriteLine(); 

      Type t = cli.GetType(); 

      foreach (System.Reflection.FieldInfo fi in t.GetFields()) 
      { 
       table.Columns.Add(fi.Name, fi.FieldType); 
       //Console.WriteLine(fi.Name + ": " + fi.GetValue(cli)); 
      } 

      foreach (System.Reflection.PropertyInfo pi in t.GetProperties()) 
      { 
       table.Columns.Add(pi.Name, pi.PropertyType); 
       //Console.WriteLine(pi.Name + ": " + pi.GetValue(cli, null)); 
      } 

      break; 
     } // Next cli 

     return table; 
    } 
+0

nicht, aber Sie können ein Attribut wie PositionAttribute (Position = 1) usw. –

+0

@Adrian Iftode erstellen: Argh, ich würde lieber dann meine eigenen Serializer schreiben. –

+0

Die meisten der Serializer verwenden Attribut basierte Serialisierung Metadaten über Eigenschaften, Klassen zu bekommen .. –

Antwort

0

Die Reihenfolge der Felder zurückgegeben wird nicht garantiert um gleich zu sein, obwohl häufig die Reihenfolge definiert ist.

Ich schlage vor, Sie verwenden Linq, um die zurückgegebene Array auf eine konsistente Weise zu bestellen und dann Ihre konvertieren.

+0

Einstellung [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.Layo utKind.Sequential)] auf allen Arten ist ein akzeptabler „Betrieb Kosten ":) –

+0

Ja, ich bin mir dessen bewusst. Aber ich erinnere mich in einer anderen Frage SO Probleme damit, und es war jemand wie Jon Skeet sagen ot. Daher sagte ich nicht garantiert. – Aliostad

+0

@Quandary Ich glaube, meine Lösung eine einfache und praktische ist. – Aliostad

0

Können Sie nicht einfach ColumnMappings in der SqlBulkCopy -Instanz festlegen, um eine Identitätszuordnung basierend auf Spaltennamen hinzuzufügen?

Wenn die Datenquelle und die Zieltabelle, die die gleiche Anzahl von Spalten haben, und die Ordnungsposition jeder Quellenspalte innerhalb der Datenquelle, um die Ordnungsposition des entsprechenden Zielspalts übereinstimmt, die Column Sammlung ist unnötig . Wenn sich die Spaltenanzahl jedoch unterscheidet oder die Ordinalpositionen nicht konsistent sind, müssen Sie ColumnMappings verwenden, um sicherzustellen, dass Daten in die richtigen Spalten kopiert werden.

z. Wenn Sie jede Spalte hinzufügen, rufen Sie einfach .Add(ColumnName,ColumnName).

+0

Zögernd, weil ich die gleiche Klasse für BulkCopy überall benutzen. Dies ist/kann nicht überall das gewünschte Verhalten sein. –