.NET 4.0升级至4.6.1后出现序列化错误求助
解决Npgsql 3.x升级后DataTable.WriteXml序列化PostgreSQL数组的错误
刚踩过类似的版本升级坑,我来给你拆解问题根源和可行的解决办法:
问题本质
Npgsql 2.x和3.x对PostgreSQL数组的处理逻辑完全不同:
- 2.x版本里,PostgreSQL数组会被自动转换成逗号分隔的字符串或者简单的.NET集合,DataTable.WriteXml能直接识别并序列化;
- 3.x则改用原生的
NpgsqlArray<T>类型封装数组,这个类型默认没实现IXmlSerializable接口,DataTable的Xml序列化机制根本不认识它,自然就抛出序列化错误了。
三种实用解决办法
1. 查询时直接把数组转成字符串(最省心快速)
在调用存储过程的SQL语句里,用PostgreSQL自带的array_to_string函数把数组转成普通字符串,这样DataTable里拿到的就是常规string类型,序列化毫无压力:
-- 示例:将string[]类型的array_col转成逗号分隔的字符串 SELECT array_to_string(array_col, ',') AS array_col, other_columns FROM your_stored_procedure();
2. 在C#里手动转换DataTable中的数组列
如果不想修改SQL,可以在拿到DataTable后,遍历行把NpgsqlArray<T>转成可序列化的格式,比如逗号分隔字符串或者List:
using (MemoryStream memoryStream = new MemoryStream()) { // 先处理所有数组列 foreach (DataRow row in dataTable.Rows) { // 替换成你实际的数组列名,这里以string[]为例 var arrayValue = row["target_array_column"] as NpgsqlArray<string>; if (arrayValue != null) { // 转成逗号分隔字符串,也可以转成List<string> row["target_array_column"] = string.Join(",", arrayValue); } } // 再执行序列化操作 dataTable.WriteXml(memoryStream, XmlWriteMode.IgnoreSchema); // ...后续业务逻辑 }
3. 全局配置Npgsql类型映射,让数组返回原生.NET集合
如果希望所有数组列都自动转成可序列化的类型,可以在程序启动时配置Npgsql的全局类型映射,把PostgreSQL数组映射为List<T>:
// 在初始化数据库连接前添加这段配置 NpgsqlConnection.GlobalTypeMapper.MapArray<string>().To<List<string>>(); // 若有其他类型的数组(比如int[]),同样添加对应映射 NpgsqlConnection.GlobalTypeMapper.MapArray<int>().To<List<int>>();
这样从数据库读取数组时,会直接得到List<string>这类原生集合,DataTable.WriteXml能正常序列化它(会生成<Item>元素的集合)。
小提示
如果存储过程返回多种类型的数组,要么对应添加不同类型的映射,要么直接用第一种SQL转换的方式,会更省心。
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

