使用sql linq查询的结果导致数据库查询两次

Jus*_*der 1 c# linq-to-sql

我查询数据库并使用以下两种方法将结果推送到控制台和文件:

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等)

我很确定这是一个非常常见的问题,但使用谷歌并没有让我更聪明,所以我转向你们:-)

mat*_*ser 6

每次访问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 .

编辑:更改为删除我的意见,并在评论中反映讨论.我个人认为编译器应该假设链接查询的最终结果是立即运行,除非你明确说明它将在以后进一步修改.只是为了避免它不可避免地导致的运行时错误.