最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中實(shí)現(xiàn)SQL Server的批量更新功能

 更新時(shí)間:2025年12月29日 09:05:35   作者:StevenChen85  
你需要在 C# 中實(shí)現(xiàn) SQL Server 的批量更新功能,不同數(shù)據(jù)量場(chǎng)景對(duì)應(yīng)不同最優(yōu)方案(小數(shù)據(jù)量簡(jiǎn)潔高效、大數(shù)據(jù)量高性能低損耗),下面詳細(xì)講解每種方案的實(shí)現(xiàn)代碼、適用場(chǎng)景及注意事項(xiàng),需要的朋友可以參考下

一、 小數(shù)據(jù)量批量更新(1000 條以?xún)?nèi),簡(jiǎn)潔高效)

適用于更新數(shù)據(jù)量較少(如幾百條)的場(chǎng)景,實(shí)現(xiàn)簡(jiǎn)單、無(wú)需額外依賴(lài),核心分為「拼接 SQL 語(yǔ)句」和「參數(shù)化 SQL(推薦,防注入)」兩種方式。

方案 1:參數(shù)化 SQL 拼接(防 SQL 注入,推薦)

通過(guò)拼接帶參數(shù)的 UPDATE 語(yǔ)句,批量執(zhí)行更新,兼顧簡(jiǎn)潔性和安全性,避免 SQL 注入風(fēng)險(xiǎn)。

實(shí)現(xiàn)代碼

using System;
using System.Data.SqlClient;

namespace SqlServerBatchUpdate
{
    class SmallDataBatchUpdate
    {
        // 數(shù)據(jù)庫(kù)連接字符串(根據(jù)你的實(shí)際環(huán)境修改)
        private static readonly string _connectionString = "Data Source=你的服務(wù)器名;Initial Catalog=你的數(shù)據(jù)庫(kù)名;User ID=你的用戶(hù)名;Password=你的密碼;";

        /// <summary>
        /// 批量更新員工薪資(小數(shù)據(jù)量)
        /// </summary>
        public static void BatchUpdateEmployeeSalary()
        {
            // 模擬需要更新的數(shù)據(jù)(實(shí)際可從業(yè)務(wù)邏輯中獲取)
            var updateList = new List<Employee>()
            {
                new Employee { EmployeeID = 1, Salary = 5500 },
                new Employee { EmployeeID = 2, Salary = 6600 },
                new Employee { EmployeeID = 3, Salary = 7700 }
            };

            // 拼接參數(shù)化SQL語(yǔ)句
            var sqlBuilder = new System.Text.StringBuilder();
            var sqlParameters = new List<SqlParameter>();

            for (int i = 0; i < updateList.Count; i++)
            {
                var emp = updateList[i];
                // 定義唯一參數(shù)名,避免沖突
                string paramIdName = $"@EmpID{i}";
                string paramSalaryName = $"@EmpSalary{i}";

                // 拼接UPDATE語(yǔ)句(每條數(shù)據(jù)對(duì)應(yīng)一個(gè)UPDATE,或用CASE WHEN優(yōu)化)
                sqlBuilder.AppendLine($"UPDATE Employee SET Salary = {paramSalaryName} WHERE EmployeeID = {paramIdName};");

                // 添加參數(shù)
                sqlParameters.Add(new SqlParameter(paramIdName, emp.EmployeeID));
                sqlParameters.Add(new SqlParameter(paramSalaryName, emp.Salary));
            }

            try
            {
                using (SqlConnection conn = new SqlConnection(_connectionString))
                {
                    conn.Open();
                    using (SqlCommand cmd = new SqlCommand(sqlBuilder.ToString(), conn))
                    {
                        // 添加所有參數(shù)
                        cmd.Parameters.AddRange(sqlParameters.ToArray());
                        // 執(zhí)行批量更新
                        int affectedRows = cmd.ExecuteNonQuery();
                        Console.WriteLine($"成功更新 {affectedRows} 條記錄");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"批量更新失?。簕ex.Message}");
            }
        }
    }

    // 員工實(shí)體類(lèi)
    public class Employee
    {
        public int EmployeeID { get; set; }
        public decimal Salary { get; set; }
        public string EmployeeName { get; set; }
        public string Department { get; set; }
    }
}

優(yōu)化:CASE WHEN 減少 SQL 語(yǔ)句數(shù)

上述代碼每條數(shù)據(jù)對(duì)應(yīng)一個(gè) UPDATE,可通過(guò) CASE WHEN 優(yōu)化為單條 UPDATE,提升執(zhí)行效率:

public static void BatchUpdateEmployeeSalaryWithCaseWhen()
{
    var updateList = new List<Employee>()
    {
        new Employee { EmployeeID = 1, Salary = 5500 },
        new Employee { EmployeeID = 2, Salary = 6600 },
        new Employee { EmployeeID = 3, Salary = 7700 }
    };

    var caseBuilder = new System.Text.StringBuilder();
    var idList = new List<int>();
    var sqlParameters = new List<SqlParameter>();

    // 拼接CASE WHEN語(yǔ)句
    caseBuilder.Append("UPDATE Employee SET Salary = CASE EmployeeID ");
    for (int i = 0; i < updateList.Count; i++)
    {
        var emp = updateList[i];
        string paramIdName = $"@EmpID{i}";
        string paramSalaryName = $"@EmpSalary{i}";

        caseBuilder.AppendLine($"WHEN {paramIdName} THEN {paramSalaryName} ");
        sqlParameters.Add(new SqlParameter(paramIdName, emp.EmployeeID));
        sqlParameters.Add(new SqlParameter(paramSalaryName, emp.Salary));
        idList.Add(emp.EmployeeID);
    }
    caseBuilder.Append("END ");
    // 拼接WHERE條件,限定更新范圍
    caseBuilder.Append("WHERE EmployeeID IN (");
    caseBuilder.Append(string.Join(",", idList));
    caseBuilder.Append(");");

    try
    {
        using (SqlConnection conn = new SqlConnection(_connectionString))
        {
            conn.Open();
            using (SqlCommand cmd = new SqlCommand(caseBuilder.ToString(), conn))
            {
                cmd.Parameters.AddRange(sqlParameters.ToArray());
                int affectedRows = cmd.ExecuteNonQuery();
                Console.WriteLine($"成功更新 {affectedRows} 條記錄");
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"批量更新失敗:{ex.Message}");
    }
}

方案 2:循環(huán)單條更新(最簡(jiǎn)單,不推薦大數(shù)據(jù)量)

逐行遍歷數(shù)據(jù),執(zhí)行單條 UPDATE 語(yǔ)句,實(shí)現(xiàn)最簡(jiǎn)單,但性能較差(多次數(shù)據(jù)庫(kù)連接 / 交互),僅適用于極少數(shù)據(jù)(幾十條以?xún)?nèi))。

實(shí)現(xiàn)代碼

public static void LoopSingleUpdate()
{
    var updateList = new List<Employee>()
    {
        new Employee { EmployeeID = 1, Salary = 5500 },
        new Employee { EmployeeID = 2, Salary = 6600 }
    };

    string sql = "UPDATE Employee SET Salary = @Salary WHERE EmployeeID = @EmployeeID;";

    try
    {
        using (SqlConnection conn = new SqlConnection(_connectionString))
        {
            conn.Open();
            foreach (var emp in updateList)
            {
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
                    cmd.Parameters.AddWithValue("@Salary", emp.Salary);
                    cmd.Parameters.AddWithValue("@EmployeeID", emp.EmployeeID);
                    cmd.ExecuteNonQuery();
                }
            }
            Console.WriteLine("全部更新完成");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"更新失?。簕ex.Message}");
    }
}

二、 大數(shù)據(jù)量批量更新(1000 條以上,高性能)

當(dāng)更新數(shù)據(jù)量較大(如 1 萬(wàn)、10 萬(wàn)甚至百萬(wàn)級(jí))時(shí),上述小數(shù)據(jù)量方案會(huì)出現(xiàn)性能瓶頸(多次交互、事務(wù)日志暴漲),推薦以下兩種高性能方案。

方案 1:使用 SqlBulkCopy + 臨時(shí)表(最優(yōu)推薦,超高效率)

核心思路:

  1. 將需要更新的數(shù)據(jù)先通過(guò) SqlBulkCopy 批量插入 SQL Server 臨時(shí)表;
  2. 通過(guò) JOIN 語(yǔ)法,將臨時(shí)表與目標(biāo)表關(guān)聯(lián),執(zhí)行批量更新;
  3. 刪除臨時(shí)表(可選,自動(dòng)臨時(shí)表會(huì)自動(dòng)銷(xiāo)毀)。

該方案最大限度減少數(shù)據(jù)庫(kù)交互,利用 SqlBulkCopy 的高性能批量寫(xiě)入能力,是大數(shù)據(jù)量更新的首選。

實(shí)現(xiàn)代碼

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;

namespace SqlServerBatchUpdate
{
    class BigDataBatchUpdate
    {
        private static readonly string _connectionString = "Data Source=你的服務(wù)器名;Initial Catalog=你的數(shù)據(jù)庫(kù)名;User ID=你的用戶(hù)名;Password=你的密碼;";

        /// <summary>
        /// 大數(shù)據(jù)量批量更新(SqlBulkCopy + 臨時(shí)表)
        /// </summary>
        public static void BatchUpdateWithBulkCopy()
        {
            // 模擬10000條需要更新的數(shù)據(jù)(實(shí)際可從業(yè)務(wù)中獲?。?
            var updateList = new List<Employee>();
            for (int i = 1; i <= 10000; i++)
            {
                updateList.Add(new Employee { EmployeeID = i, Salary = 5000 + i * 10 });
            }

            // 1. 將List轉(zhuǎn)換為DataTable(SqlBulkCopy支持DataTable入?yún)ⅲ?
            DataTable tempDt = ConvertListToDataTable(updateList);

            try
            {
                using (SqlConnection conn = new SqlConnection(_connectionString))
                {
                    conn.Open();
                    // 開(kāi)啟事務(wù),確保操作原子性
                    using (SqlTransaction tran = conn.BeginTransaction())
                    {
                        try
                        {
                            // 2. 創(chuàng)建臨時(shí)表(#開(kāi)頭為局部臨時(shí)表,僅當(dāng)前連接可見(jiàn))
                            string createTempTableSql = @"
                                CREATE TABLE #TempEmployee (
                                    EmployeeID INT PRIMARY KEY,
                                    Salary DECIMAL(18, 2) NOT NULL
                                );";
                            using (SqlCommand cmd = new SqlCommand(createTempTableSql, conn, tran))
                            {
                                cmd.ExecuteNonQuery();
                            }

                            // 3. SqlBulkCopy 批量插入臨時(shí)表
                            using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, tran))
                            {
                                bulkCopy.DestinationTableName = "#TempEmployee"; // 目標(biāo)臨時(shí)表名
                                bulkCopy.BatchSize = 1000; // 每批次插入1000條
                                bulkCopy.BulkCopyTimeout = 30; // 超時(shí)時(shí)間30秒

                                // 映射DataTable列與臨時(shí)表列(列名一致可省略,建議顯式映射)
                                bulkCopy.ColumnMappings.Add("EmployeeID", "EmployeeID");
                                bulkCopy.ColumnMappings.Add("Salary", "Salary");

                                // 執(zhí)行批量插入
                                bulkCopy.WriteToServer(tempDt);
                            }

                            // 4. 關(guān)聯(lián)臨時(shí)表與目標(biāo)表,執(zhí)行批量更新
                            string batchUpdateSql = @"
                                UPDATE E
                                SET E.Salary = T.Salary,
                                    E.UpdateTime = GETDATE()
                                FROM Employee E
                                INNER JOIN #TempEmployee T
                                ON E.EmployeeID = T.EmployeeID;";
                            using (SqlCommand cmd = new SqlCommand(batchUpdateSql, conn, tran))
                            {
                                int affectedRows = cmd.ExecuteNonQuery();
                                Console.WriteLine($"成功更新 {affectedRows} 條記錄");
                            }

                            // 5. 刪除臨時(shí)表(可選,局部臨時(shí)表連接關(guān)閉后自動(dòng)銷(xiāo)毀)
                            string dropTempTableSql = "DROP TABLE #TempEmployee;";
                            using (SqlCommand cmd = new SqlCommand(dropTempTableSql, conn, tran))
                            {
                                cmd.ExecuteNonQuery();
                            }

                            // 提交事務(wù)
                            tran.Commit();
                        }
                        catch (Exception ex)
                        {
                            // 出錯(cuò)回滾事務(wù)
                            tran.Rollback();
                            Console.WriteLine($"批量更新失?。簕ex.Message}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"數(shù)據(jù)庫(kù)連接失敗:{ex.Message}");
            }
        }

        /// <summary>
        /// List轉(zhuǎn)DataTable(通用方法)
        /// </summary>
        private static DataTable ConvertListToDataTable<T>(List<T> list)
        {
            DataTable dt = new DataTable();
            var properties = typeof(T).GetProperties();

            // 添加DataTable列
            foreach (var prop in properties)
            {
                dt.Columns.Add(prop.Name, prop.PropertyType);
            }

            // 填充DataTable數(shù)據(jù)
            foreach (var item in list)
            {
                DataRow row = dt.NewRow();
                foreach (var prop in properties)
                {
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                }
                dt.Rows.Add(row);
            }

            return dt;
        }
    }
}

方案 2:使用 Dapper 框架(簡(jiǎn)潔高效,第三方庫(kù))

Dapper 是輕量級(jí) ORM 框架,簡(jiǎn)化數(shù)據(jù)庫(kù)操作,支持批量更新,通過(guò)拼接參數(shù)化 SQL 或使用 Execute 方法批量執(zhí)行,兼顧簡(jiǎn)潔性和性能,需先安裝 Dapper 包。

步驟 1:安裝 Dapper 包

通過(guò) NuGet 安裝:Install-Package Dapper 或 dotnet add package Dapper

實(shí)現(xiàn)代碼

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using Dapper;

namespace SqlServerBatchUpdate
{
    class DapperBatchUpdate
    {
        private static readonly string _connectionString = "Data Source=你的服務(wù)器名;Initial Catalog=你的數(shù)據(jù)庫(kù)名;User ID=你的用戶(hù)名;Password=你的密碼;";

        /// <summary>
        /// Dapper 批量更新
        /// </summary>
        public static void BatchUpdateWithDapper()
        {
            var updateList = new List<Employee>()
            {
                new Employee { EmployeeID = 1, Salary = 5500 },
                new Employee { EmployeeID = 2, Salary = 6600 },
                new Employee { EmployeeID = 3, Salary = 7700 }
            };

            try
            {
                using (SqlConnection conn = new SqlConnection(_connectionString))
                {
                    conn.Open();
                    // 批量執(zhí)行更新(Dapper自動(dòng)處理參數(shù))
                    string sql = "UPDATE Employee SET Salary = @Salary WHERE EmployeeID = @EmployeeID;";
                    int affectedRows = conn.Execute(sql, updateList);
                    Console.WriteLine($"成功更新 {affectedRows} 條記錄");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Dapper批量更新失?。簕ex.Message}");
            }
        }
    }
}

三、 關(guān)鍵注意事項(xiàng)(避坑指南)

  1. 防 SQL 注入:始終使用「參數(shù)化 SQL」(避免直接拼接字符串),無(wú)論是原生 ADO.NET 還是 Dapper,參數(shù)化查詢(xún)是防止 SQL 注入的核心。
  2. 事務(wù)保護(hù):批量更新屬于關(guān)鍵操作,建議開(kāi)啟事務(wù)(SqlTransaction),確保所有更新要么全部成功,要么全部回滾,避免數(shù)據(jù)不一致。
  3. 連接釋放:使用 using 語(yǔ)句包裹 SqlConnection、SqlCommand 等對(duì)象,自動(dòng)釋放數(shù)據(jù)庫(kù)連接資源,避免連接泄露。
  4. 批量大小控制:使用 SqlBulkCopy 時(shí),合理設(shè)置 BatchSize(建議 1000~5000),過(guò)大可能占用過(guò)多內(nèi)存,過(guò)小會(huì)降低效率。
  5. 索引優(yōu)化:目標(biāo)表的關(guān)聯(lián)字段(如 EmployeeID)建議建立主鍵或索引,提升 JOIN 操作和 WHERE 篩選的效率。
  6. 超時(shí)設(shè)置:大數(shù)據(jù)量更新時(shí),適當(dāng)調(diào)整 CommandTimeout(默認(rèn) 30 秒),避免因執(zhí)行時(shí)間過(guò)長(zhǎng)導(dǎo)致超時(shí)。

總結(jié)

  1. 小數(shù)據(jù)量(<1000 條):優(yōu)先使用「參數(shù)化 SQL + CASE WHEN」(原生 ADO.NET)或 Dapper,簡(jiǎn)潔高效。
  2. 大數(shù)據(jù)量(≥1000 條):首選「SqlBulkCopy + 臨時(shí)表」,性能最優(yōu),最大限度減少數(shù)據(jù)庫(kù)交互。
  3. 開(kāi)發(fā)效率優(yōu)先:使用 Dapper 框架,簡(jiǎn)化代碼編寫(xiě),兼顧性能和可讀性。
  4. 數(shù)據(jù)安全優(yōu)先:開(kāi)啟事務(wù)保護(hù)、使用參數(shù)化查詢(xún)、合理釋放連接資源。

以上就是C#中實(shí)現(xiàn)SQL Server的批量更新功能的詳細(xì)內(nèi)容,更多關(guān)于C# SQL Server批量更新的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

玉环县| 澄江县| 灵山县| 昌邑市| 轮台县| 武汉市| 府谷县| 浦江县| 阿拉善右旗| 迁西县| 沙河市| 黄骅市| 牡丹江市| 广安市| 贵州省| 茂名市| 景东| 滨州市| 余姚市| 乌拉特前旗| 宁陕县| 泾源县| 永善县| 张家口市| 左云县| 合阳县| 晋州市| 洮南市| 普定县| 沂南县| 云林县| 长白| 科尔| 密山市| 安宁市| 潞西市| 平陆县| 达拉特旗| 图片| 颍上县| 循化|