V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
PendingOni
V2EX  ›  程序员

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

  •  
  •   PendingOni ·
    KomiSans · 56 天前 · 785 次点击
    这是一个创建于 56 天前的主题,其中的信息可能已经有所发展或是发生改变。
    
        /// <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

    7 条回复    2022-08-10 21:46:18 +08:00
    INCerry
        1
    INCerry  
       56 天前
    看了下 反射的那块效率会有点低 其它地方都没啥问题
    PendingOni
        2
    PendingOni  
    OP
       56 天前
    @INCerry 有可能的 不过暂时想不到除了用遍历模型列表进行反射添加 Row 到 DataTable 之外更好的方法
    Bazingal
        3
    Bazingal  
       56 天前
    @PendingOni 用 source generators 和多态,编译期生成各个 model 的 ToSqlBulkCopyDataTable 方法
    PendingOni
        4
    PendingOni  
    OP
       56 天前
    @Bazingal 感谢指导 我去研究下
    Bazingal
        5
    Bazingal  
       56 天前
    @PendingOni 上面有一点说错了,你的 3 个泛型方法都要生成
    wdwwtzy
        6
    wdwwtzy  
       56 天前   ❤️ 1
    @PendingOni emit 呢?
    PendingOni
        7
    PendingOni  
    OP
       56 天前
    @wdwwtzy emit? 这个反射的方法暂时还没有试过 我去查下相关文档
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1411 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 00:27 · PVG 08:27 · LAX 17:27 · JFK 20:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.