2012-04-04 34 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