zoukankan      html  css  js  c++  java
  • List<T> To IDatareader For SqlBulkCopy

    原文地址:http://www.csvreader.com/csv_downloads.php 或 

         http://technico.qnownow.com/custom-data-reader-to-bulk-copy-data-from-object-collection-to-sql-server/

    使用场景:

      项目中通过业务逻辑生产了多个大List<T>对象,需要使用bcp方式保存到数据库,有两种方式:

    1.把List<T>转成DataTable,然后保存。确定就是内存占用很多。

     2.实现一个IDataReader对象,解决内存增长问题。

    通用的转换代码如下:

      1 public class GenericListDataReader<T> : IDataReader
      2     {
      3         private IEnumerator<T> list = null;
      4         private List<PropertyInfo> properties = new List<PropertyInfo>();
      5 
      6         public GenericListDataReader(IEnumerable<T> list)
      7         {
      8             this.list = list.GetEnumerator();
      9             foreach (PropertyInfo property in typeof(T).GetProperties(
     10                 BindingFlags.GetProperty |
     11                 BindingFlags.Instance |
     12                 BindingFlags.Public))
     13             {
     14                 if (
     15                     property.PropertyType.IsPrimitive ||
     16                     property.PropertyType == typeof(string) ||
     17                     property.PropertyType == typeof(DateTime)
     18                     )
     19                 {
     20                     properties.Add(property);
     21                 }
     22             }
     23         }
     24 
     25         #region IDataReader Members
     26 
     27         public void Close()
     28         {
     29             list.Dispose();
     30         }
     31 
     32         public int Depth
     33         {
     34             get { throw new NotImplementedException(); }
     35         }
     36 
     37         public DataTable GetSchemaTable()
     38         {
     39             throw new NotImplementedException();
     40         }
     41 
     42         public bool IsClosed
     43         {
     44             get { throw new NotImplementedException(); }
     45         }
     46 
     47         public bool NextResult()
     48         {
     49             throw new NotImplementedException();
     50         }
     51 
     52         public bool Read()
     53         {
     54             return list.MoveNext();
     55         }
     56 
     57         public int RecordsAffected
     58         {
     59             get { throw new NotImplementedException(); }
     60         }
     61 
     62         #endregion
     63 
     64         #region IDisposable Members
     65 
     66         public void Dispose()
     67         {
     68             Close();
     69         }
     70 
     71         #endregion
     72 
     73         #region IDataRecord Members
     74 
     75         public int FieldCount
     76         {
     77             get { return properties.Count; }
     78         }
     79 
     80         public bool GetBoolean(int i)
     81         {
     82             throw new NotImplementedException();
     83         }
     84 
     85         public byte GetByte(int i)
     86         {
     87             throw new NotImplementedException();
     88         }
     89 
     90         public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
     91         {
     92             throw new NotImplementedException();
     93         }
     94 
     95         public char GetChar(int i)
     96         {
     97             throw new NotImplementedException();
     98         }
     99 
    100         public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    101         {
    102             throw new NotImplementedException();
    103         }
    104 
    105         public IDataReader GetData(int i)
    106         {
    107             throw new NotImplementedException();
    108         }
    109 
    110         public string GetDataTypeName(int i)
    111         {
    112             throw new NotImplementedException();
    113         }
    114 
    115         public DateTime GetDateTime(int i)
    116         {
    117             throw new NotImplementedException();
    118         }
    119 
    120         public decimal GetDecimal(int i)
    121         {
    122             throw new NotImplementedException();
    123         }
    124 
    125         public double GetDouble(int i)
    126         {
    127             throw new NotImplementedException();
    128         }
    129 
    130         public Type GetFieldType(int i)
    131         {
    132             return properties[i].PropertyType;
    133         }
    134 
    135         public float GetFloat(int i)
    136         {
    137             throw new NotImplementedException();
    138         }
    139 
    140         public Guid GetGuid(int i)
    141         {
    142             throw new NotImplementedException();
    143         }
    144 
    145         public short GetInt16(int i)
    146         {
    147             throw new NotImplementedException();
    148         }
    149 
    150         public int GetInt32(int i)
    151         {
    152             throw new NotImplementedException();
    153         }
    154 
    155         public long GetInt64(int i)
    156         {
    157             throw new NotImplementedException();
    158         }
    159 
    160         public string GetName(int i)
    161         {
    162             return properties[i].Name;
    163         }
    164 
    165         public int GetOrdinal(string name)
    166         {
    167             throw new NotImplementedException();
    168         }
    169 
    170         public string GetString(int i)
    171         {
    172             throw new NotImplementedException();
    173         }
    174 
    175         public object GetValue(int i)
    176         {
    177             return properties[i].GetValue(list.Current, null);
    178         }
    179 
    180         public int GetValues(object[] values)
    181         {
    182             throw new NotImplementedException();
    183         }
    184 
    185         public bool IsDBNull(int i)
    186         {
    187             throw new NotImplementedException();
    188         }
    189 
    190         public object this[string name]
    191         {
    192             get { throw new NotImplementedException(); }
    193         }
    194 
    195         public object this[int i]
    196         {
    197             get { throw new NotImplementedException(); }
    198         }
    199 
    200         #endregion
    201     }
    View Code

    调用方法

     1 using (GenericListDataReader<Candidate> reader = new GenericListDataReader<Candidate>(candidates))
     2 using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.Database))
     3 using (SqlBulkCopy bcp = new SqlBulkCopy(conn))
     4 {
     5     conn.Open();
     6 
     7     bcp.DestinationTableName = "candidates";
     8 
     9     string createTableSql = "";
    10 
    11     createTableSql += "IF EXISTS(SELECT * FROM sys.tables t WHERE t.name = '" 
    12         + bcp.DestinationTableName + "') DROP TABLE " + bcp.DestinationTableName + ";";
    13     createTableSql += "CREATE TABLE dbo." + bcp.DestinationTableName + "(";
    14 
    15     for (int column = 0; column < reader.FieldCount; column++)
    16     {
    17         if (column > 0)
    18         {
    19             createTableSql += ",";
    20         }
    21 
    22         createTableSql += "[" + reader.GetName(column) + "]" + " VARCHAR(MAX) NULL";
    23     }
    24 
    25     createTableSql += ");";
    26 
    27     using (SqlCommand createTable = new SqlCommand(createTableSql, conn))
    28     {
    29         createTable.ExecuteNonQuery();
    30     }
    31 
    32     bcp.WriteToServer(reader);
    33 }
    View Code

     这个转换是按照反射后对象的属性顺序与数据库里的字段顺序对应,工作中可能这两个顺序不一致,所以我定义了另外的一种方式:

    基类

      1   public class ColumnInfo
      2     {
      3         public string ColumnName { get; set; }
      4 
      5         public Type ColumnType { get; set; }
      6 
      7         public Func<object> GetValueFunc { get; set; }
      8 
      9         public ColumnInfo(string name, Type type, Func<object> func)
     10         {
     11             this.ColumnName = name;
     12             this.ColumnType = type;
     13             this.GetValueFunc = func;
     14         }
     15     }
     16 
     17     public abstract class ReportReaderBase<T> : IDataReader
     18     {
     19         public readonly IEnumerator<T> List;
     20         public abstract Dictionary<int, ColumnInfo> ColumnInfoDic { get; }
     21 
     22         protected StrategyReportReaderBase(List<T> list)
     23         {
     24             this.List = list.GetEnumerator();
     25             //if (this.List.Current == null)
     26             //    this.List.MoveNext();
     27         }
     28 
     29 
     30         #region IDataReader Members
     31 
     32         public void Close()
     33         {
     34             this.List.Dispose();
     35         }
     36 
     37         public int Depth
     38         {
     39             get { throw new NotImplementedException(); }
     40         }
     41 
     42         public DataTable GetSchemaTable()
     43         {
     44             throw new NotImplementedException();
     45         }
     46 
     47         public bool IsClosed
     48         {
     49             get { throw new NotImplementedException(); }
     50         }
     51 
     52         public bool NextResult()
     53         {
     54             throw new NotImplementedException();
     55         }
     56 
     57         public bool Read()
     58         {
     59             return this.List.MoveNext();
     60         }
     61 
     62         public int RecordsAffected
     63         {
     64             get { throw new NotImplementedException(); }
     65         }
     66 
     67         #endregion
     68 
     69         #region IDisposable Members
     70 
     71         public void Dispose()
     72         {
     73             Close();
     74         }
     75 
     76         #endregion
     77 
     78         #region IDataRecord Members
     79 
     80         public int FieldCount
     81         {
     82             get { return this.ColumnInfoDic.Count; }
     83         }
     84 
     85         public bool GetBoolean(int i)
     86         {
     87             throw new NotImplementedException();
     88         }
     89 
     90         public byte GetByte(int i)
     91         {
     92             throw new NotImplementedException();
     93         }
     94 
     95         public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
     96         {
     97             throw new NotImplementedException();
     98         }
     99 
    100         public char GetChar(int i)
    101         {
    102             throw new NotImplementedException();
    103         }
    104 
    105         public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    106         {
    107             throw new NotImplementedException();
    108         }
    109 
    110         public IDataReader GetData(int i)
    111         {
    112             throw new NotImplementedException();
    113         }
    114 
    115         public string GetDataTypeName(int i)
    116         {
    117             throw new NotImplementedException();
    118         }
    119 
    120         public DateTime GetDateTime(int i)
    121         {
    122             throw new NotImplementedException();
    123         }
    124 
    125         public decimal GetDecimal(int i)
    126         {
    127             throw new NotImplementedException();
    128         }
    129 
    130         public double GetDouble(int i)
    131         {
    132             throw new NotImplementedException();
    133         }
    134 
    135         public Type GetFieldType(int i)
    136         {
    137             return this.ColumnInfoDic[i].ColumnType;
    138         }
    139 
    140         public float GetFloat(int i)
    141         {
    142             throw new NotImplementedException();
    143         }
    144 
    145         public Guid GetGuid(int i)
    146         {
    147             throw new NotImplementedException();
    148         }
    149 
    150         public short GetInt16(int i)
    151         {
    152             throw new NotImplementedException();
    153         }
    154 
    155         public int GetInt32(int i)
    156         {
    157             throw new NotImplementedException();
    158         }
    159 
    160         public long GetInt64(int i)
    161         {
    162             throw new NotImplementedException();
    163         }
    164 
    165         public string GetName(int i)
    166         {
    167             return this.ColumnInfoDic[i].ColumnName;
    168         }
    169 
    170         public int GetOrdinal(string name)
    171         {
    172             throw new NotImplementedException();
    173         }
    174 
    175         public string GetString(int i)
    176         {
    177             throw new NotImplementedException();
    178         }
    179 
    180         public object GetValue(int i)
    181         {
    182             return this.ColumnInfoDic[i].GetValueFunc.Invoke();
    183         }
    184 
    185         public int GetValues(object[] values)
    186         {
    187             throw new NotImplementedException();
    188         }
    189 
    190         public bool IsDBNull(int i)
    191         {
    192             throw new NotImplementedException();
    193         }
    194 
    195         public object this[string name]
    196         {
    197             get { throw new NotImplementedException(); }
    198         }
    199 
    200         public object this[int i]
    201         {
    202             get { throw new NotImplementedException(); }
    203         }
    204 
    205         #endregion
    206     }
    View Code

    子类

     1    public class CalcBmReader :    ReportReaderBase<RptCalcBMEO>
     2     {
     3 
     4         private readonly Guid _reportID;
     5 
     6         public RptCalcBmReader(List<RptCalcBMEO> list, Guid reportID)
     7             : base(list)
     8         {
     9             this._reportID = reportID;
    10         }
    11 
    12         public override Dictionary<int, ColumnInfo> ColumnInfoDic
    13         {
    14             get
    15             {
    16                 return new Dictionary<int, ColumnInfo>
    17                 {
    18                     {0, new ColumnInfo("RptCalcBMID",typeof(Guid), () => Guid.NewGuid())},
    19                     {1,  new ColumnInfo("MFReportID",typeof(string), () => this._reportID)},
    20                     {2,  new ColumnInfo("CalcDate",typeof(string),()=>this.List.Current.CalcDate)},
    21                     {3,  new ColumnInfo("Type",typeof(int),()=>this.List.Current.Type)},
    22                     {4,  new ColumnInfo("ReturnRate",typeof(decimal),()=>this.List.Current.ReturnRate)},
    23                     {5,  new ColumnInfo("CumRR",typeof(decimal?), () => this.List.Current.CumRR.HasValue ? this.List.Current.CumRR : null)},
    24                 };
    25             }
    26 
    27         }
    28     }
    View Code

    调用

    1      using (var rptCalcBmReader = new RptFSubAdjDetailReader(factorAdj.RptFSubAdjDetails, reportID, rptFSubAdjID))
    2                                 using (var bcp = db.CreateBcp(SqlBulkCopyOptions.Default))
    3                                 {
    4                                     bcp.DestinationTableName = _rptFSubAdjDetailTableName;
    5                                     bcp.WriteToServer(rptCalcBmReader);
    6                                 }
    View Code
  • 相关阅读:
    【线程控制:线程休眠】
    【线程调度-优先级】
    【多线程实现方案一:继承Thread 类】
    【多线程概述】
    【使用Mybatis-Generator自动生成Mapper、Model、Mapping相关文件】
    【springmvc集成mybatis框架】
    【UltraISO制作centos7系统安装盘】
    【己有原码, 为何还有反码和补码?】
    【原码, 反码, 补码的基础概念和计算方法】
    【数据类型】
  • 原文地址:https://www.cnblogs.com/zhaobl/p/ListToIDatareaderForSqlBulkCopy.html
Copyright © 2011-2022 走看看