我查询数据库并使用以下两种方法将结果推送到控制台和文件:
var result = from p in _db.Pages
join r in rank on p.PkId equals r.Key
orderby r.NumPages descending
select new KeyNameCount
{
PageID = p.PkId,
PageName = p.Name,
Count = r.NumPages
};
WriteFindingsToFile(result, parentId);
WriteFindingsToConsole(result, parentId);
Run Code Online (Sandbox Code Playgroud)
当用作两个方法调用中的参数时,IEnumerable <T>,而不是IQuerable <T>用作结果的参数类型.
在两次调用中,结果都在foreach中迭代.这导致针对数据库的两个相同的调用,每个方法一个.
我可以将这两个方法重构为一个并且只使用一个foreach,但这很快就会变得非常难以维护(添加写入html,写入xml等)
我很确定这是一个非常常见的问题,但使用谷歌并没有让我更聪明,所以我转向你们:-)
每次访问LINQ查询时,它都会重新查询数据库以刷新数据.要阻止这种情况的发生,请使用.ToArray()或.ToList().
例如
var result = (from p in _db.Pages
select p).ToList(); //will query now
Write(result); //will not requery
Write(result2); //will not requery
Run Code Online (Sandbox Code Playgroud)
重要的是要理解原始LINQ查询在使用时运行,而不是在代码中编写时(例如,在此之前不要丢弃_db).
当你意识到它是如何工作时,这可能会令人惊讶.这允许方法链接和稍后修改查询反映在DB上的最终查询运行中.重要的是要始终牢记,因为它可能导致在编译时不会捕获的运行时错误,通常是因为在使用列表之前关闭了数据库连接,因为您传递的似乎是一个简单的IEnumerable .
编辑:更改为删除我的意见,并在评论中反映讨论.我个人认为编译器应该假设链接查询的最终结果是立即运行,除非你明确说明它将在以后进一步修改.只是为了避免它不可避免地导致的运行时错误.