我使用ExcelMapper读取了一个Excel,得到
var excelData = new ExcelMapper(workbook) { HeaderRow = false, MinRowNumber = 2 }
.Fetch<UsersExcelModel>().Select((p, i) => { p.RowNo = i + 3; return p; });
之后,修改excelData的内容
foreach (var item in excelData)
{item.UserStatus= UserStatus.OnLine;
}
让我费解现象出现了:在foreach中修改枚举UserStatus的值成功,但出了循环,excelData里的UserStatus枚举值还是老样子。
class列表是引用类型,不是值类型,我只是修改引用类型属性的值,又不是修改它的引用,怎么会这样?
一番苦找,最终确定,这是IEnumerable<>的延迟执行的特性所导致的。
因为ExcelMapperFetch返回的是IEnumerable<>类型,而IEnumerable<>自带延迟执行。每次遍历IEnumerable<>,查询都会重新执行。如果底层数据源(如数据库上下文、一个每次返回新实例的工厂方法)在两次遍历之间发生了变化,或者查询本身会生成新对象(例如使用了 Select投影),那么第二次遍历到的对象,很可能已经不是第一次遍历时修改的那个对象了。这就造成了“循环内修改有效,循环外看似无效”的假象。
解决方案:在excelData后增加.ToList(),让结果立刻加载“固化”到内存中,阻止其延迟执行。
var excelData= new ExcelMapper(workbook) { HeaderRow = false, MinRowNumber = 2 }
.Fetch<UsersExcelModel>().Select((p, i) => { p.RowNo = i + 3; return p; }).ToList();