.net ORM框架dapper批量插入

news2025/6/7 15:53:03

.NET ORM 框架 Dapper 批量插入全解析

在 .NET 开发中,与数据库交互是常见需求。Dapper 作为轻量级的 ORM(对象关系映射)库,在简化数据库交互方面表现出色。今天我们就来深入探讨 Dapper 实现批量插入的几种方法。

为什么需要批量插入

在实际业务场景中,当需要向数据库插入大量数据时,如果采用单条插入的方式,会频繁与数据库进行交互,导致性能下降。而批量插入可以将多个插入操作合并为一次,减少数据库交互次数,从而显著提高性能。

方法一:Execute 方法与 Table - Valued Parameters (TVP)

适用场景

这种方法适用于支持 TVP 的数据库,例如 SQL Server。

实现步骤

  1. 创建用户定义的表类型:在 SQL Server 中创建一个用户定义的表类型,用于存储要插入的数据。
CREATE TYPE dbo.MyTableType AS TABLE
(
    Id INT,
    Name NVARCHAR(50)
);
  1. 创建存储过程:编写一个存储过程,接收用户定义的表类型作为参数,并将数据插入到目标表中。
CREATE PROCEDURE dbo.InsertMyTable
    @MyTable dbo.MyTableType READONLY
AS
BEGIN
    INSERT INTO MyTable (Id, Name)
    SELECT Id, Name FROM @MyTable;
END
  1. C# 代码实现:在 C# 中使用 Dapper 调用存储过程进行批量插入。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Dapper;

public class MyEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Program
{
    public static void Main()
    {
        string connectionString = "connection_string";
        using (IDbConnection dbConnection = new SqlConnection(connectionString))
        {
            List<MyEntity> entities = new List<MyEntity>
            {
                new MyEntity { Id = 1, Name = "Name1" },
                new MyEntity { Id = 2, Name = "Name2" }
            };

            var table = new DataTable();
            table.Columns.Add("Id", typeof(int));
            table.Columns.Add("Name", typeof(string));

            foreach (var entity in entities)
            {
                table.Rows.Add(entity.Id, entity.Name);
            }

            string sql = "EXEC dbo.InsertMyTable @MyTable";
            var param = new { MyTable = table.AsTableValuedParameter("dbo.MyTableType") };
            dbConnection.Execute(sql, param);
        }
    }
}

注意事项

AsTableValuedParameter 方法是 Dapper.Contrib 或其他扩展库的一部分,你可能需要安装相应的 NuGet 包。

独特见解

这种方法将数据封装在用户定义的表类型中,通过存储过程进行插入,使得数据库操作更加安全和高效。但需要在数据库端进行额外的配置,增加了一定的维护成本。

方法二:SqlBulkCopy 高效批量插入

适用场景

对于大量数据的批量插入,SqlBulkCopy 是最佳选择。

代码示例

using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (var bulkCopy = new SqlBulkCopy(connection))
    {
        bulkCopy.DestinationTableName = "MyTable";
        bulkCopy.ColumnMappings.Add("Name", "Name");
        bulkCopy.ColumnMappings.Add("Age", "Age");

        var table = new DataTable();
        table.Columns.Add("Name", typeof(string));
        table.Columns.Add("Age", typeof(int));

        table.Rows.Add("Alice", 25);
        table.Rows.Add("Bob", 30);
        table.Rows.Add("Charlie", 35);

        bulkCopy.WriteToServer(table);
    }
}

优点

性能极高,适合处理大量数据。它直接将数据批量写入数据库,避免了多次 SQL 语句的执行,大大提高了插入效率。

独特见解

SqlBulkCopy 是专门为批量插入设计的,在处理大量数据时优势明显。但它只能用于 SQL Server 数据库,缺乏一定的跨数据库兼容性。

方法三:使用事务批量插入

实现思路

通过事务将多个插入操作打包,确保原子性。如果其中一个插入操作失败,整个事务将回滚,保证数据的一致性。

代码示例

using (var connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (var transaction = connection.BeginTransaction())
    {
        try
        {
            var sql = "INSERT INTO MyTable (Name, Age) VALUES (@Name, @Age)";
            var users = new[]
            {
                new { Name = "Alice", Age = 25 },
                new { Name = "Bob", Age = 30 },
                new { Name = "Charlie", Age = 35 }
            };

            connection.Execute(sql, users, transaction);
            transaction.Commit();
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

优点

确保所有插入操作要么全部成功,要么全部失败,保证了数据的完整性。

独特见解

事务机制在处理数据插入时非常重要,尤其是在对数据一致性要求较高的场景中。但事务的使用会增加一定的性能开销,需要根据实际情况进行权衡。

方法四:使用自定义扩展方法

实现思路

结合 Dapper 和 SqlBulkCopy 实现一个高效的批量插入扩展方法。

代码示例

public static class DapperExtensions
{
    public static void BulkInsert<T>(this IDbConnection connection, string tableName, IEnumerable<T> data)
    {
        using (var bulkCopy = new SqlBulkCopy(connection.ConnectionString))
        {
            bulkCopy.DestinationTableName = tableName;
            var table = new DataTable();
            var properties = typeof(T).GetProperties();

            foreach (var prop in properties)
            {
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
                bulkCopy.ColumnMappings.Add(prop.Name, prop.Name);
            }

            foreach (var item in data)
            {
                var row = table.NewRow();
                foreach (var prop in properties)
                {
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                }
                table.Rows.Add(row);
            }

            bulkCopy.WriteToServer(table);
        }
    }
}

// 使用示例
using (var connection = new SqlConnection(connectionString))
{
    var users = new[]
    {
        new User { Name = "Alice", Age = 25 },
        new User { Name = "Bob", Age = 30 },
        new User { Name = "Charlie", Age = 35 }
    };

    connection.BulkInsert("MyTable", users);
}

优点

结合了 Dapper 的灵活性和 SqlBulkCopy 的高性能,同时通过扩展方法简化了代码的使用。

独特见解

自定义扩展方法提高了代码的复用性和可维护性。开发人员可以根据不同的业务需求,灵活调整扩展方法的实现。

总结

在选择批量插入方法时,需要根据实际情况进行权衡:

  • 小批量数据:可以使用 Execute 方法或事务,实现简单,能满足基本需求。
  • 大量数据:优先选择 SqlBulkCopy,以获得最佳的性能。
  • 简化代码:可以使用 Dapper.Contrib 或自定义扩展方法,提高开发效率。

通过合理选择和使用 Dapper 的批量插入方法,能够显著提升 .NET 应用程序与数据库交互的性能。

前些天发现了一个比较好玩的人工智能学习网站,通俗易懂,风趣幽默,可以了解了解AI基础知识,人工智能教程,不是一堆数学公式和算法的那种,用各种举例子来学习,读起来比较轻松,有兴趣可以看一下。
人工智能教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2403078.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++11 右值引用:从入门到精通

文章目录 一、引言二、左值和右值&#xff08;一&#xff09;概念&#xff08;二&#xff09;区别和判断方法 三、左值引用和右值引用&#xff08;一&#xff09;左值引用&#xff08;二&#xff09;右值引用 四、移动语义&#xff08;一&#xff09;概念和必要性&#xff08;二…

.net 使用MQTT订阅消息

在nuGet下载M2Mqtt V4.3.0版本。&#xff08;支持.net framework&#xff09; 订阅主题 public void LoadMQQCData() {string enpoint "xxx.xxx.x.x";//ip地址int port 1883;//端口string user "usrname";//用户名string pwd "pwd";//密码…

【递归、搜索与回溯】综合练习(四)

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人递归&#xff0c;搜索与回溯算法的学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码…

强化学习入门:Gym实现CartPole随机智能体

前言 最近想开一个关于强化学习专栏&#xff0c;因为DeepSeek-R1很火&#xff0c;但本人对于LLM连门都没入。因此&#xff0c;只是记录一些类似的读书笔记&#xff0c;内容不深&#xff0c;大多数只是一些概念的东西&#xff0c;数学公式也不会太多&#xff0c;还望读者多多指教…

STM32:CAN总线精髓:特性、电路、帧格式与波形分析详解

声明&#xff1a;此博客是我的学习笔记&#xff0c;所看课程是江协科技的CAN总线课程&#xff0c;知识点都大同小异&#xff0c;我仅进行总结并加上了我自己的理解&#xff0c;所引案例也都是课程中的案例&#xff0c;希望对你的理解有所帮助&#xff01; 知识点1【CAN总线的概…

贝叶斯深度学习!华科大《Nat. Commun.》发表BNN重大突破!

华科大提出基于贝叶斯深度学习的超分辨率成像&#xff0c;成功被Nat. Commun.收录。可以说&#xff0c;这是贝叶斯神经网络BNN近期最值得关注的成果之一了。另外还有AAAI 2025上的Bella新框架&#xff0c;计算成本降低了99.7%&#xff0c;也非常值得研读。 显然鉴于BNN“不确定…

【大模型LLM学习】Flash-Attention的学习记录

【大模型LLM学习】Flash-Attention的学习记录 0. 前言1. flash-attention原理简述2. 从softmax到online softmax2.1 safe-softmax2.2 3-pass safe softmax2.3 Online softmax2.4 Flash-attention2.5 Flash-attention tiling 0. 前言 Flash Attention可以节约模型训练和推理时间…

物联网数据归档之数据存储方案选择分析

在上一篇文章中《物联网数据归档方案选择分析》中凯哥分析了归档设计的两种方案,并对两种方案进行了对比。这篇文章咱们就来分析分析,归档后数据应该存储在哪里?及存储方案对比。 这里就选择常用的mysql及taos数据库来存储归档后的数据吧。 你在处理设备归档表存储方案时对…

【C语言】C语言经典小游戏:贪吃蛇(上)

文章目录 一、游戏背景及其功能二、Win32 API介绍1、Win32 API2、控制台程序3、定位坐标&#xff08;COORD&#xff09;4、获得句柄&#xff08;GetStdHandle&#xff09;5、获得光标属性&#xff08;GetConsoleCursorInfo&#xff09;1&#xff09;描述光标属性&#xff08;CO…

vue2中使用jspdf插件实现页面自定义块pdf下载

pdf下载 实现pdf下载的环境安装jspdf插件在项目中使用 实现pdf下载的环境 项目需求案例背景&#xff0c;点击【pdf下载】按钮&#xff0c;弹出pdf下载弹窗&#xff0c;显示需要下载四个模块的下载进度&#xff0c;下载完成后&#xff0c;关闭弹窗即可&#xff01; 项目使用的是…

如何防止服务器被用于僵尸网络(Botnet)攻击 ?

防止服务器被用于僵尸网络&#xff08;Botnet&#xff09;攻击是关键的网络安全措施之一。僵尸网络是黑客利用大量被感染的计算机、服务器或物联网设备来发起攻击的网络。以下是关于如何防止服务器被用于僵尸网络攻击的技术文章&#xff1a; 防止服务器被用于僵尸网络&#xff…

基于cornerstone3D的dicom影像浏览器 第二十九章 自定义菜单组件

文章目录 前言一、程序结构1. 菜单数据结构2. XMenu.vue3. XSubMenu.vue4. XSubMenuSlot.vue5. XMenuItem.vue 二、调用流程总结 前言 菜单用于组织程序功能&#xff0c;为用户提供导航。是用户与程序交互非常重要的接口。 开源组件库像Element Plus和Ant Design中都提供了功能…

【Block总结】DBlock,结合膨胀空间注意模块(Di-SpAM)和频域模块Gated-FFN|即插即用|CVPR2025

论文信息 标题: DarkIR: Robust Low-Light Image Restoration 作者: Daniel Feijoo, Juan C. Benito, Alvaro Garcia, Marcos Conde 论文链接&#xff1a;https://arxiv.org/pdf/2412.13443 GitHub链接&#xff1a;https://github.com/cidautai/DarkIR 创新点 DarkIR提出了…

口罩佩戴检测算法AI智能分析网关V4工厂/工业等多场景守护公共卫生安全

一、引言​ 在公共卫生安全日益受到重视的当下&#xff0c;口罩佩戴成为预防病毒传播、保障人员健康的重要措施。为了高效、精准地实现对人员口罩佩戴情况的监测&#xff0c;AI智能分析网关V4口罩检测方案应运而生。该方案依托先进的人工智能技术与强大的硬件性能&#xff0c;…

Double/Debiased Machine Learning

独立同步分布的观测数据 { W i ( Y i , D i , X i ) ∣ i ∈ { 1 , . . . , n } } \{W_i(Y_i,D_i,X_i)| i\in \{1,...,n\}\} {Wi​(Yi​,Di​,Xi​)∣i∈{1,...,n}}&#xff0c;其中 Y i Y_i Yi​表示结果变量&#xff0c; D i D_i Di​表示因变量&#xff0c; X i X_i Xi​表…

HarmonyOS Next 弹窗系列教程(4)

HarmonyOS Next 弹窗系列教程&#xff08;4&#xff09; 介绍 本章主要介绍和用户点击关联更加密切的菜单控制&#xff08;Menu&#xff09; 和 气泡提示&#xff08;Popup&#xff09; 它们出现显示弹窗出现的位置都是在用户点击屏幕的位置相关 菜单控制&#xff08;Menu&…

【C】-递归

1、递归概念 递归&#xff08;Recursion&#xff09;是编程中一种重要的解决问题的方法&#xff0c;其核心思想是函数通过调用自身来解决规模更小的子问题&#xff0c;直到达到最小的、可以直接解决的基准情形&#xff08;Base Case&#xff09;。 核心&#xff1a;自己调用…

飞马LiDAR500雷达数据预处理

0 引言 在使用飞马D2000无人机搭载LiDAR500进行作业完成后&#xff0c;需要对数据进行预处理&#xff0c;方便给内业人员开展点云分类等工作。在开始操作前&#xff0c;先了解一下使用的软硬件及整体流程。 0.1 外业测量设备 无人机&#xff1a;飞马D2000S激光模块&#xff…

嵌入式鸿蒙开发环境搭建操作方法与实现

Linux环境搭建镜像下载链接: 链接:https://pan.baidu.com/s/1F2f8ED5V1KwLjyYzKVx2yQ 提取码:Leun vscode和Linux系统连接的详细过程1.下载Visual Studio Code

QT常用控件(1)

控件是构成QT的基础元素&#xff0c;例如Qwidget也是一个控件&#xff0c;提供了一个‘空’的矩形&#xff0c;我们可以往里面添加内容和处理用户输入&#xff0c;例如&#xff1a;按钮&#xff08;QpushButton&#xff09;&#xff0c;基础显示控件&#xff08;Lable&#xff…