C# WPF 基于XML实现SQL Server数据库数据插入与更新
原需求梳理
使用Oldtable.xml员工数据文件同步SQL Server 2014中的tblemp表,规则为:XML中记录在表中已存在则更新对应字段,不存在则插入新记录,在C# WPF项目中实现该逻辑。
用到的XML结构
<?xml version="1.0" encoding="UTF-8"?> <ty> <ry> <EMPID>1</EMPID> <EMPName>Thabo</EMPName> <EMPRole>Developer </EMPRole> <EMPAddress>227 Complex B WoodMans Road Claremont</EMPAddress> <EMPEmail>Thabecoo@hotmail.com</EMPEmail> <EMPNumber>083 577 8910</EMPNumber> </ry> <ry> <EMPID>2</EMPID> <EMPName>Aldrin</EMPName> <EMPRole>Analyst </EMPRole> <EMPAddress>65 Mfecane Avenue</EMPAddress> <EMPEmail>AGFFHH@tommail.com</EMPEmail> <EMPNumber>0872343352</EMPNumber> </ry> <ry> <EMPID>4</EMPID> <EMPName>Amoleng</EMPName> <EMPRole>Engineer </EMPRole> <EMPAddress>43 Pixely KaSeme Street</EMPAddress> <EMPEmail>AmoT@axxess.co.za</EMPEmail> <EMPNumber>0765546832</EMPNumber> </ry> <ry> <EMPID>5</EMPID> <EMPName>Nathi</EMPName> <EMPRole>Executive </EMPRole> <EMPAddress>54 Steve Biko Road</EMPAddress> <EMPEmail>nat544787@gmail.com</EMPEmail> <EMPNumber>0834567656</EMPNumber> </ry> </ty>
原代码问题说明
- 原有INSERT语句逻辑错误,无法实现更新已有记录的需求
- 读取XML节点的逻辑错误:
EMPID是ry的子元素而非属性,用Attribute方法无法获取 - 缺少打开数据库连接、执行SQL命令的核心逻辑
优化实现方案
直接用SQL Server自带的MERGE语句实现插入/更新二合一逻辑,无需额外导出导入表数据,代码简单易维护。
需引入的命名空间
using System; using System.IO; using System.Data; using System.Data.SqlClient; using System.Xml.Linq;
完整实现代码
void SyncEmpDataFromXml() { try { // 1. 读取数据库连接串 string connConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Connection.xml"); XDocument connDoc = XDocument.Load(connConfigPath); string connStr = connDoc.Descendants("connectionStrings").FirstOrDefault()?.Value; if (string.IsNullOrWhiteSpace(connStr)) { // 可自行添加连接串为空的提示逻辑 return; } // 2. 读取员工XML数据 string xmlPath = @"C:\Users\user1\Desktop\Oldtable.xml"; // 建议改成配置项,不要写死绝对路径 XDocument empDoc = XDocument.Load(xmlPath); var empNodes = empDoc.Descendants("ry").ToList(); if (empNodes.Count == 0) return; // 3. 编写MERGE语句(支持存在更新、不存在插入) string mergeSql = @" MERGE INTO tblemp AS Target USING (VALUES (@EMPID, @EMPName, @EMPRole, @EMPAddress, @EMPEmail, @EMPNumber)) AS Source (EMPID, EMPName, EMPRole, EMPAddress, EMPEmail, EMPNumber) ON Target.EMPID = Source.EMPID WHEN MATCHED THEN UPDATE SET EMPName = Source.EMPName, EMPRole = Source.EMPRole, EMPAddress = Source.EMPAddress, EMPEmail = Source.EMPEmail, EMPNumber = Source.EMPNumber WHEN NOT MATCHED THEN INSERT (EMPID, EMPName, EMPRole, EMPAddress, EMPEmail, EMPNumber) VALUES (Source.EMPID, Source.EMPName, Source.EMPRole, Source.EMPAddress, Source.EMPEmail, Source.EMPNumber); "; // 4. 批量执行同步 using (SqlConnection con = new SqlConnection(connStr)) { con.Open(); using (SqlCommand cmd = new SqlCommand(mergeSql, con)) { // 预先添加参数,避免循环内重复创建 cmd.Parameters.Add("@EMPID", SqlDbType.Int); cmd.Parameters.Add("@EMPName", SqlDbType.NVarChar, 50); cmd.Parameters.Add("@EMPRole", SqlDbType.NVarChar, 50); cmd.Parameters.Add("@EMPAddress", SqlDbType.NVarChar, 200); cmd.Parameters.Add("@EMPEmail", SqlDbType.NVarChar, 100); cmd.Parameters.Add("@EMPNumber", SqlDbType.NVarChar, 20); foreach (var emp in empNodes) { // 给参数赋值 cmd.Parameters["@EMPID"].Value = Convert.ToInt32(emp.Element("EMPID")?.Value); cmd.Parameters["@EMPName"].Value = emp.Element("EMPName")?.Value ?? string.Empty; cmd.Parameters["@EMPRole"].Value = emp.Element("EMPRole")?.Value ?? string.Empty; cmd.Parameters["@EMPAddress"].Value = emp.Element("EMPAddress")?.Value ?? string.Empty; cmd.Parameters["@EMPEmail"].Value = emp.Element("EMPEmail")?.Value ?? string.Empty; cmd.Parameters["@EMPNumber"].Value = emp.Element("EMPNumber")?.Value ?? string.Empty; cmd.ExecuteNonQuery(); } } } // 可自行添加同步完成的提示逻辑 } catch (Exception ex) { // 可自行添加异常捕获、日志记录、错误提示逻辑 Console.WriteLine($"同步失败:{ex.Message}"); } }
注意事项
- 确保
tblemp表的EMPID字段是主键或有唯一索引,保证MERGE匹配逻辑正确 - 如果XML数据量超过1000条,建议改用批量导入临时表再执行MERGE的方案,性能更高
- 可将XML路径、字段长度等配置项放到配置文件中,方便后续修改
内容的提问来源于stack exchange,提问作者Mholi Zindela
相关产品推荐
相关产品推荐

