C#使用SqlDataReader读取SQL Server数据填充主从列表的优化方法咨询
C# 嵌套主从对象填充的优化方案
一、原生ADO.NET优化方案(无第三方依赖)
你原有的实现逻辑是可行的,仅需调整部分细节就可以大幅提升可读性和鲁棒性:
- 修正原代码拼写问题:你定义的Master类属性为
List<Detail> Details,原逻辑中写的h.Detail属于拼写错误,容易触发空引用异常 - 用字典缓存已创建的Master对象,无需依赖查询结果按Master ID排序,逻辑更清晰:
List<Master> result = new List<Master>(); Dictionary<int, Master> masterCache = new Dictionary<int, Master>(); // 避免SELECT *,明确指定字段减少无效数据传输 string sqlCommand = "SELECT m.ID, m.Name, d.Description, d.Amount FROM Master m LEFT JOIN Detail d on m.ID = d.ID"; using (var dr = db.DbDataReader as System.Data.SqlClient.SqlDataReader) { while (dr.Read()) { int masterId = dr.GetInt32("ID"); // 缓存中不存在则创建Master对象 if (!masterCache.TryGetValue(masterId, out var currentMaster)) { currentMaster = new Master { ID = masterId, Name = dr.GetString("Name"), Details = new List<Detail>() // 提前初始化避免后续空值判断 }; masterCache.Add(masterId, currentMaster); result.Add(currentMaster); } // 跳过左连接产生的空Detail记录 if (!dr.IsDBNull("Description")) { currentMaster.Details.Add(new Detail { Description = dr.GetString("Description"), Amount = dr.GetDouble("Amount") }); } } }
二、微型ORM方案(推荐,大幅减少样板代码)
使用Dapper这类轻量ORM,无需手动处理DataReader的字段映射、类型转换,性能和原生ADO.NET几乎无差异:
// 先安装Dapper的NuGet包 using Dapper; using System.Data.SqlClient; string sqlCommand = "SELECT m.ID, m.Name, d.ID, d.Description, d.Amount FROM Master m LEFT JOIN Detail d on m.ID = d.ID"; using (var conn = new SqlConnection("你的数据库连接字符串")) { var masterDict = new Dictionary<int, Master>(); var result = conn.Query<Master, Detail, Master>(sqlCommand, (master, detail) => { if (!masterDict.TryGetValue(master.ID, out var existingMaster)) { existingMaster = master; existingMaster.Details = new List<Detail>(); masterDict.Add(existingMaster.ID, existingMaster); } if (detail != null) { existingMaster.Details.Add(detail); } return existingMaster; }, splitOn: "ID") // 指定两个对象的拆分字段,第二个ID对应Detail表的主键 .Distinct() .ToList(); }
三、额外优化建议
- 补全Detail类的属性类型定义,原代码中
Description和Amount未指定类型会触发编译错误,建议修改为public string Description { get; set; }和public double Amount { get; set; } - 若数据量较大,可改为两次查询:先查询所有Master记录,再查询所有关联的Detail记录,最后在内存中做关联,避免左连接导致的Master字段重复传输,数据量越大优化效果越明显
内容的提问来源于stack exchange,提问作者Blishton
相关产品推荐
相关产品推荐

