2013-08-29 36 views
3

我的目标是从数据源检索数据,向其中添加一些元数据并将其插入另一个目标。如何向DataReader添加列

该目标具有四个多列然后是源(计算列)的架构。

我正在使用SqlBulkCopy,它需要一个阅读器与所有列(包括4计算)。

有没有办法给DataReader手动添加列?或者如果它不可能有什么替代方案我的数据插入?

回答

2

有可能

  • 创建自己的类,它实现IDataReader的接口
  • 根据需要从基础的DataReader或返回的结果在类的构造函数添加现有的DataReader
  • 倍率接口返回你自己的计算值

只是为了得到一个想法,这可能是一个简单的实现(我跳过了大多数方法)

public class WrapperDataReader : IDataReader 
{ 
    private IDataReader reader; 

    public WrapperDataReader(IDataReader reader) 
    { 
     this.reader = reader; 
    } 

    public void Close() 
    { 
     reader.Close(); 
    } 

    public int Depth 
    { 
     get { return reader.Depth; } 
    } 

    public DataTable GetSchemaTable() 
    { 
     var schemaTable = reader.GetSchemaTable(); 
     // add your computed column to the schema table 
     schemaTable.Rows.Add(...); 
     return schemaTable; 
    } 

    public bool GetBoolean(int i) 
    { 
     return reader.GetBoolean(i); 
    } 

    public int GetOrdinal(string name) 
    { 
     if (name.Equals("displayName", StringComparison.InvariantCultureIgnoreCase)) 
      return 15; 
     return reader.GetOrdinal(name); 
    } 

    public string GetString(int i) 
    { 
     if (i == 15) 
      return String.Format("{0}, {1}", GetString(1), GetString(2)); // lastname, firstname 
     return reader.GetString(i); 
    } 

} 

更新

既然你propably使用在WriteToServer方法,你可以使用接受一个DataTable重载代替。

 var connectionString = "..."; 
     var copy = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.Default); 
     copy.DestinationTableName = "Customers"; 

     var reader = new SqlDataReader(); 
     var table = new DataTable(); 
     table.Load(reader); 
     table.Columns.Add("DisplayName", typeof(string), "lastname, firstname"); 
     table.Columns.Add("CustomerCode", typeof(string)); 

     foreach (DataRow row in table.Rows) 
      row["CustomerCode"] = ((int)row["id"] + 10000).ToString(); 

     copy.WriteToServer(table); 
+0

我有一些困难,实现GetBytes方法.. –

+0

你真的需要实现GetBytes会()方法自己吗?为什么不将该方法传递给基础DataReader? 'return reader.GetBytes(i,fieldOffset,buffer,bufferoffset,length);' –

+1

@Yosi其实你不需要实现'GetBytes',也不需要像'GetSchemaTable'这样复杂的东西,如果你所要做的只是使用这个类作为'SqlBulkCopy'的包装器,它使用的'IDataReader'的唯一方法是'bool IsDbNull(int)','bool Read()','int GetOrdnal(string)','GetValue(int)',和'int FieldCount'属性。其他的都可以抛出一个'NotImplmentedException()',我不得不这样做我自己,这就是所需要的。 –

1

一个DataReader是一个只读结构,所以它不能被修改。 您可以改用DataTable

1

数据读取器仅用于读取数据。您无法修改其模式或数据值。数据集/数据表就是为此目的而设计的。

0

,我发现了另一个可能的解决方案,我目前使用:

  1. 从现有DataReader创建下列对象:
    IEnumerable<object[]> - 它代表了数据
    List<Column> - 它代表数据列DataReader

  2. 修改数据,并添加额外的列

  3. 创建方法AsDataReader(IEnumerable<object[]> updatedData,updatedColumns List<Column>)它获取更新的对象和收益*修改DataReader

    • 我用来回报收益率来提高性能。