[Snippet]-Csharp 批量导入助手 代码片段

2022-08-10 15:44:46 +08:00
 PendingOni

    /// <summary>
    /// 批量插入助手
    /// </summary>
    public static class BulkHelper
    {
        /// <summary>
        /// 批量导入入口
        /// </summary>
        /// <param name="con">DbConnection 数据库连接资源</param>
        /// <param name="models">实体列表</param>
        /// <param name="tableName">表名</param>
        /// <typeparam name="T">实体泛型</typeparam>
        public static void BulkCopy<T>(DbConnection con, List<T> models, string tableName = null)
        {
            BulkInsert(con, models, tableName);
        }

        /// <summary>
        /// IList 的扩展方法 用于集合转换 DataTable 类
        /// </summary>
        /// <param name="models">实体列表</param>
        /// <param name="tableName">表名</param>
        /// <typeparam name="T">实体泛型</typeparam>
        /// <returns>DataTable</returns>
        private static DataTable ToSqlBulkCopyDataTable<T>(this List<T> models, string tableName = null)
        {
            var props = TypeDescriptor.GetProperties(typeof(T));

            var table = new DataTable
            {
                TableName = tableName?.ToLowerInvariant() ?? typeof(T).Name.ToLowerInvariant()
            };

            // 表中 字段(列)的填充
            foreach (PropertyDescriptor prop in props)
            {
                var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
                if (type.IsEnum) type = typeof(int);

                table.Columns.Add(prop.Name.ToLowerInvariant(), type);
            }

            // 表中 数据内容的填充
            foreach (var data in models)
            {
                var newRow = table.NewRow();
                foreach (PropertyDescriptor prop in props)
                {
                    newRow[prop.Name.ToLowerInvariant()] = prop.GetValue(data) ?? DBNull.Value;
                }

                table.Rows.Add(newRow);
            }

            return table;
        }

        /// <summary>
        /// 批量导入或修改
        /// </summary>
        /// <param name="con">DbConnection 数据库资源</param>
        /// <param name="datas">实体列表</param>
        /// <param name="tableName">表名</param>
        /// <typeparam name="T">实体泛型</typeparam>
        private static void BulkInsert<T>(DbConnection con, List<T> datas, string tableName)
        {
            // 数据模型列表转换 DataTable
            var tb = datas.ToSqlBulkCopyDataTable(tableName);

            var ops = new BulkOperation(con);
            // 批量插入 引用 Z.BulkOperations
            ops.BulkInsert(tb);
        }
    }

不知性能上和 EF Core 比会不会好一些 gist 地址-> https://gist.github.com/KomiSans/9824c2352f5efdee68bc70bd6917616a

1226 次点击
所在节点    程序员
7 条回复
INCerry
2022-08-10 18:46:18 +08:00
看了下 反射的那块效率会有点低 其它地方都没啥问题
PendingOni
2022-08-10 19:01:43 +08:00
@INCerry 有可能的 不过暂时想不到除了用遍历模型列表进行反射添加 Row 到 DataTable 之外更好的方法
Bazingal
2022-08-10 19:40:41 +08:00
@PendingOni 用 source generators 和多态,编译期生成各个 model 的 ToSqlBulkCopyDataTable 方法
PendingOni
2022-08-10 20:16:31 +08:00
@Bazingal 感谢指导 我去研究下
Bazingal
2022-08-10 20:28:56 +08:00
@PendingOni 上面有一点说错了,你的 3 个泛型方法都要生成
wdwwtzy
2022-08-10 21:01:40 +08:00
@PendingOni emit 呢?
PendingOni
2022-08-10 21:46:18 +08:00
@wdwwtzy emit? 这个反射的方法暂时还没有试过 我去查下相关文档

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/871953

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX