123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Data.SqlClient;
- using System.Linq;
- using System.Reflection;
- using System.Text;
- using System.Threading.Tasks;
- namespace Ant.Service.Utility
- {
- public enum Gender
- {
- Man = 1,
- Woman
- }
- public class User
- {
- public Guid Id { get; set; }
- public string Name { get; set; }
- public Gender? Gender { get; set; }
- public int? Age { get; set; }
- public int? CityId { get; set; }
- public DateTime? OpTime { get; set; }
- }
- public static class SqlConnectionExtension
- {
- /// <summary>
- /// 测试代码
- /// </summary>
- public static void test()
- {
- List<User> usersToInsert = new List<User>();
- usersToInsert.Add(new User() { Id = Guid.NewGuid(), Name = "so1", Gender = Gender.Man, Age = 18, CityId = 1, OpTime = DateTime.Now });
- usersToInsert.Add(new User() { Id = Guid.NewGuid(), Name = "so2", Gender = Gender.Man, Age = 19, CityId = 2, OpTime = DateTime.Now });
- usersToInsert.Add(new User() { Id = Guid.NewGuid(), Name = "so3", Gender = Gender.Man, Age = 20, CityId = 3, OpTime = DateTime.Now });
- usersToInsert.Add(new User() { Id = Guid.NewGuid(), Name = "so4", Gender = Gender.Man, Age = 21, CityId = 4, OpTime = DateTime.Now });
- using (SqlConnection conn = new SqlConnection("Data Source = .;Initial Catalog = Chloe;Integrated Security = SSPI;"))
- {
- conn.BulkCopy(usersToInsert, 20000, "Users");
- }
- }
- /// <summary>
- /// 使用 SqlBulkCopy 向 destinationTableName 表插入数据
- /// </summary>
- /// <typeparam name="TModel">必须拥有与目标表所有字段对应属性</typeparam>
- /// <param name="conn"></param>
- /// <param name="modelList">要插入的数据</param>
- /// <param name="batchSize">SqlBulkCopy.BatchSize每次传输的行数</param>
- /// <param name="destinationTableName">如果为 null,则使用 TModel 名称作为 destinationTableName</param>
- /// <param name="bulkCopyTimeout">SqlBulkCopy.BulkCopyTimeout</param>
- /// <param name="externalTransaction">要使用的事务</param>
- public static void BulkCopy<TModel>(this SqlConnection conn, List<TModel> modelList, int batchSize, string destinationTableName = null, int? bulkCopyTimeout = null, SqlTransaction externalTransaction = null)
- {
- bool shouldCloseConnection = false;
- if (string.IsNullOrEmpty(destinationTableName))
- destinationTableName = typeof(TModel).Name;
- DataTable dtToWrite = ToSqlBulkCopyDataTable(modelList, conn, destinationTableName);
- SqlBulkCopy sbc = null;
- try
- {
- if (externalTransaction != null)
- sbc = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, externalTransaction);
- else
- sbc = new SqlBulkCopy(conn);
- using (sbc)
- {
- sbc.BatchSize = batchSize;//每次传输的行数
- sbc.DestinationTableName = destinationTableName;
- if (bulkCopyTimeout != null)
- sbc.BulkCopyTimeout = bulkCopyTimeout.Value;
- if (conn.State != ConnectionState.Open)
- {
- shouldCloseConnection = true;
- conn.Open();
- }
- sbc.WriteToServer(dtToWrite);
- }
- }
- finally
- {
- if (shouldCloseConnection && conn.State == ConnectionState.Open)
- conn.Close();
- }
- }
- /// <summary>
- ///
- /// </summary>
- /// <typeparam name="TModel"></typeparam>
- /// <param name="modelList"></param>
- /// <param name="conn"></param>
- /// <param name="tableName"></param>
- /// <returns></returns>
- public static DataTable ToSqlBulkCopyDataTable<TModel>(List<TModel> modelList, SqlConnection conn, string tableName)
- {
- DataTable dt = new DataTable();
- Type modelType = typeof(TModel);
- List<SysColumn> columns = GetTableColumns(conn, tableName);
- List<PropertyInfo> mappingProps = new List<PropertyInfo>();
- var props = modelType.GetProperties();
- for (int i = 0; i < columns.Count; i++)
- {
- var column = columns[i];
- PropertyInfo mappingProp = props.Where(a => a.Name == column.Name).FirstOrDefault();
- if (mappingProp == null)
- throw new Exception(string.Format("model 类型 '{0}'未定义与表 '{1}' 列名为 '{2}' 映射的属性", modelType.FullName, tableName, column.Name));
- mappingProps.Add(mappingProp);
- Type dataType = GetUnderlyingType(mappingProp.PropertyType);
- if (dataType.IsEnum)
- dataType = typeof(int);
- dt.Columns.Add(new DataColumn(column.Name, dataType));
- }
- foreach (var model in modelList)
- {
- DataRow dr = dt.NewRow();
- for (int i = 0; i < mappingProps.Count; i++)
- {
- PropertyInfo prop = mappingProps[i];
- object value = prop.GetValue(model);
- if (GetUnderlyingType(prop.PropertyType).IsEnum)
- {
- if (value != null)
- value = (int)value;
- }
- dr[i] = value ?? DBNull.Value;
- }
- dt.Rows.Add(dr);
- }
- return dt;
- }
- /// <summary>
- /// 获取表中所有列
- /// </summary>
- /// <param name="sourceConn"></param>
- /// <param name="tableName"></param>
- /// <returns></returns>
- static List<SysColumn> GetTableColumns(SqlConnection sourceConn, string tableName)
- {
- string sql = string.Format("select * from syscolumns inner join sysobjects on syscolumns.id=sysobjects.id where sysobjects.xtype='U' and sysobjects.name='{0}' order by syscolumns.colid asc", tableName);
- List<SysColumn> columns = new List<SysColumn>();
- using (SqlConnection conn = (SqlConnection)((ICloneable)sourceConn).Clone())
- {
- conn.Open();
- SqlCommand command = new SqlCommand(sql, conn);
- using (var reader = command.ExecuteReader())
- {
- while (reader.Read())
- {
- SysColumn column = new SysColumn();
- column.Name = reader["name"].ToString();
- column.ColOrder = reader["colorder"].ToInt32();
- columns.Add(column);
- }
- }
- conn.Close();
- }
- return columns;
- }
- static Type GetUnderlyingType(Type type)
- {
- Type unType = Nullable.GetUnderlyingType(type); ;
- if (unType == null)
- unType = type;
- return unType;
- }
- class SysColumn
- {
- public string Name { get; set; }
- public int ColOrder { get; set; }
- }
- }
- }
|