2012-04-04 38 views
0

問:我用下面的類序列化CSV文件System.Reflection,如何獲取字段和屬性的位置?

List<MyCsvFileType>

然後我用

MyConvertTo轉換List<MyCsvFileType>到DataTable

(以下也列出)。 現在的問題是,MyConvertTo更改列的位置,這意味着所有屬性在所有公共變量之後來到 。

這個問題導致的問題是之後我使用SqlBulkCopy將DataTable複製到數據庫表中。 不幸的是,SqlBulkCopy使用列的索引而不是列名來自動映射到數據庫表的數據表 。

這意味着我得到很好的錯誤消息,因爲它試圖插入浮動區域領域的字母數字AP_FL_CADKey (因爲我的數據庫表有佈局的類一樣)......

有什麼辦法我可以在MyConvertTo中獲得字段&屬性的位置? 因此,我不必更改我的數據庫表(批次)或編寫自己的BulkCopy實現, ,因爲我不想手動設置數據表和數據庫表之間的映射關係?

應該通過排序由字段偏移是可能的,在最壞的情況...

類別:

[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

不,但你可以創建一個像PositionAttribute(Position = 1)等屬性 – 2012-04-04 09:27:32

+0

@Adrian Iftode:呃,我寧願寫我自己的序列化程序。 – 2012-04-04 09:39:01

+0

大多數序列化程序使用基於屬性的序列化來獲取有關屬性,類的元數據.. – 2012-04-04 09:39:52

回答

0

的字段的順序返回的是不保證是一樣的,雖然一般是定義的順序。

我建議你使用Linq命令以一致的方式返回數組,然後使用你的轉換。

+0

在所有類型上設置[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.Layo utKind.Sequential)]是可接受的「操作費用「:) :) – 2012-04-04 09:42:04

+0

是的,我意識到這一點。但我記得在另一個SO問題中,它就像是一個像JON雙向飛碟一樣的人。所以我說沒有保證。 – Aliostad 2012-04-04 09:43:53

+0

@Quandary我認爲我的解決方案是一個簡單實用的解決方案。 – Aliostad 2012-04-04 09:44:26

0

您不能只在SqlBulkCopy實例中設置ColumnMappings來添加基於列名稱的身份映射嗎?

如果數據源和目標表具有相同的列數,並且將數據源中的每個源列的順序位置對應的目標的列的順序位置相匹配,則ColumnMappings集合是不必要。但是,如果列數不同,或者序數位置不一致,則必須使用ColumnMappings以確保將數據複製到正確的列中。

例如,當您添加每列時,請致電.Add(ColumnName,ColumnName)

+0

不情願,因爲我在任何地方使用BulkCopy相同的類。這是/可能不是所期望的行爲。 – 2012-04-04 09:37:55