如何从数据库中将数据块明智地读入内存?

时间:2013-05-28 03:22:07

标签: c# linq

基本上我想要完成的是对数据库中的大量数据执行CRUD操作(使用mvc 4,LINQ) 我这里有一张叫做消息的表。 我需要查询它并检索那些带有folderid = 10(数量超过一百万)的msgs

<List>Messages msgList = from msg in db.messages
                         where msg.folderid.equals(10)
                         select msg).tolist();

这将在msgList集合中返回一百万。 我想以块的形式检索记录,一次大约5000个。 请帮忙!

3 个答案:

答案 0 :(得分:2)

其他2个当前答案(Kuruvilla&amp; Ben)都有警告你可能需要考虑......

1)使用标志意味着您需要更新此数据库以跟踪已处理的消息..这可能是也可能不可行..但它不是唯一的方式

2)如果您确定在调用之间没有添加任何项目,则使用skip and take是一个好主意。这称为分页,这可能意味着第二页包含您已经处理过的项目,如果发生这种情况! / p>

如果其中任何一点都有问题,那么我建议按ID订购你的消息,跟踪最后处理的id并在where子句中使用它,并结合Take:

var msgList = (from msg in db.messages
               order by msg.id
               where msg.id > lastProcessedId
               select msg).Take(5000).ToList();

在处理完每条消息后保留lastProcessedId,这样就可以在出现错误的地方继续前进

答案 1 :(得分:1)

在完成第一次5000的操作并更新每条记录的标志后,你最好拥有Flag。 现在你可以拿另外5000没有上面的旗帜。

var msgList = (from msg in db.messages
                         where msg.folderid ==10 && msg.flag
                              select msg).Take(5000).ToList();

答案 2 :(得分:0)

考虑使用SkipTake来执行此类分块。阅读有关跳过的内容,然后选择herehere。在您的情况下,您可能希望包装您的查询(在查询语法中)以调用这些方法(只能以流畅的语法提供)。确保在调用Take之前使用ToList,这是将记录调入内存的时间。对于前100条记录,请使用:

var msgList = (from msg in db.messages
               where msg.folderid == 10
               select msg).Take(100).ToList();

接下来的100条记录使用:

var msgList = (from msg in db.messages
               where msg.folderid == 10
               select msg).Skip(100).Take(100).ToList();