C#控制台程序写入XML到SQL Server遇编码切换异常的解决问询
解决EF写入SQL Server XML列时的“无法切换编码”异常
问题原因
C#字符串默认是UTF-16编码,当你把带<?xml version="1.0" encoding="utf-8"?>声明的XML字符串直接传给SQL Server的xml列时,SQL Server会按声明的UTF-8去解析实际是UTF-16的内容,编码不匹配导致抛出XML parsing: line 1, character 38, unable to switch the encoding异常。
解决方案
方案一:移除XML声明中的编码属性
直接修改XML内容,去掉编码声明部分,让SQL Server自动识别字符串的实际编码(UTF-16)。
快速字符串替换
// 简单移除编码声明 string cleanedXml = xmlFileContent.Replace("encoding=\"utf-8\"", ""); // 更严谨的正则替换,避免误匹配其他内容 cleanedXml = System.Text.RegularExpressions.Regex.Replace( xmlFileContent, @"encoding=""utf-8""", "", System.Text.RegularExpressions.RegexOptions.IgnoreCase );
之后用处理后的cleanedXml替换原内容写入即可。
用XML解析器处理(更可靠)
通过XmlDocument加载XML后重新生成编码匹配的内容:
XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlFileContent); XmlWriterSettings settings = new XmlWriterSettings { OmitXmlDeclaration = false, Encoding = Encoding.Unicode // 与C#字符串编码保持一致 }; using (StringWriter sw = new StringWriter()) using (XmlWriter writer = XmlWriter.Create(sw, settings)) { doc.WriteTo(writer); writer.Flush(); string cleanedXml = sw.ToString(); // 此时cleanedXml的编码声明为utf-16,可直接写入 }
方案二:使用SqlCommand直接写入(已验证有效)
绕开EF的自动处理逻辑,用参数化SqlCommand写入,SQL Server会正确识别XML参数的编码:
public void WriteXmlTestFileToDatabase(string xmlFileContent) { string connectionString = "你的数据库连接字符串"; using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); string sql = "INSERT INTO stor.myTable (FileGuid, XmlDocument) VALUES (@FileGuid, @XmlDocument)"; using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add("@FileGuid", SqlDbType.VarChar, 36).Value = Guid.NewGuid().ToString(); // 指定参数类型为SqlDbType.Xml,自动处理编码匹配 cmd.Parameters.Add("@XmlDocument", SqlDbType.Xml).Value = xmlFileContent; cmd.ExecuteNonQuery(); } } }
方案三:改用XDocument作为EF实体属性类型
EF对XDocument类型的支持更友好,会自动处理XML编码转换:
- 修改实体类属性类型:
public partial class myTable { public long myTableId { get; set; } public string FileGuid { get; set; } public XDocument XmlDocument { get; set; } // 替换原字符串类型 }
- 读取XML文件时直接加载为XDocument:
XDocument xmlDoc = XDocument.Load("目标XML文件路径"); WriteXmlTestFileToDatabase(xmlDoc);
- 调整写入方法:
public void WriteXmlTestFileToDatabase(XDocument xmlDoc) { using (SqlServerDatabaseEntities db = new SqlServerDatabaseEntities()) { var newEntry = new myTable(); newEntry.FileGuid = Guid.NewGuid().ToString(); newEntry.XmlDocument = xmlDoc; db.myTable.Add(newEntry); db.SaveChanges(); } }
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

