C#中用IEnumerable<string>替代TextReader实现XmlSerializer反序列化
问题根因
你当前代码无法运行的核心问题有两个:
- 用
connection.Query<string>("select * from Events")写法错误:多列数据无法直接映射为字符串列表,得到的结果根本不是合法XML结构,传入反序列化方法必然失败。 - 用
DataTable.WriteXml生成的XML是DataTable专属的固定嵌套格式,和你Events类通过XML特性定义的目标结构完全不匹配,无法被正确反序列化。
最优实现方案(推荐)
完全不需要绕XML序列化/反序列化的冗余流程,直接把数据库查询结果映射为SDK要求的Events实体即可,性能更高、逻辑更简单:
- 首先补全实体类的XML映射特性,保证结构和你之前用XML文件时的格式完全对齐:
[XmlRoot("Events")] public class Events { [XmlElement("DATA")] public List<ReadEventRequestResponse.DATA> EventList { get; set; } public Events() { EventList = new List<ReadEventRequestResponse.DATA>(); } } static public class ReadEventRequestResponse { [XmlRoot(ElementName = "DATA")] public class DATA { [XmlAttribute(AttributeName = "dt")] public string LocalTime { get; set; } // 此处按你实际的表字段、XML结构补全其余属性即可,属性名和数据库列名对应,XmlAttribute参数和原XML的属性名对应 } }
- 直接用Dapper(从你之前写的
connection.Query判断你已经引入了Dapper)查询数据库映射为实体,组装成Events对象返回:
public static Events Load() { using (IDbConnection connection = new SqlConnection(Helper.CnnVal("TimeReg"))) { const string query = @" SELECT LocalTime AS dt -- 其余字段按DATA类的属性名补全别名,和原XML属性/节点名对应 FROM Events "; var dataList = connection.Query<ReadEventRequestResponse.DATA>(query).ToList(); return new Events { EventList = dataList }; } }
这个方案完全跳过了XML中间文件、XML流序列化反序列化的冗余步骤,返回的Events对象和你之前从XML文件反序列化得到的对象完全一致,可以直接传给SDK使用。
备用方案(需要XML流场景)
如果你的其他业务逻辑必须使用符合格式的XML流,不要用DataTable.WriteXml生成,直接把上面查出来的Events对象序列化为内存流即可,生成的XML结构和原XML文件完全一致:
public static Stream GetEventsXmlStream() { var events = Load(); var ms = new MemoryStream(); var xs = new XmlSerializer(typeof(Events)); xs.Serialize(ms, events); ms.Position = 0; // 必须将流指针重置到开头,否则读取时会得到空内容 return ms; }
内容的提问来源于stack exchange,提问作者Bende
相关产品推荐
相关产品推荐

