我们目前有一个作为Windows服务运行的生产应用程序。很多时候,这个应用程序最终会在一个可能需要几个小时才能完成的循环中结束。我们正在使用.net 4.0的Entity Framework来进行数据访问。
我正在寻找确认,如果我们将新数据加载到系统中,在初始化此循环之后,它将不会导致项目被添加到循环本身。当循环初始化时,我们正在寻找那个时刻的“数据”。虽然我相对肯定这将完全像使用ADO并对数据进行循环(循环仅循环通过初始化时存在的数据),但我正在寻找同事的确认。
提前感谢您的帮助。
// update:这是c#中的一些示例代码 - 问题是相同的,如果将新项添加到EF正在查询的表中,枚举是否会更改?
IEnumerable<myobject> myobjects = (from o in db.theobjects where o.id==myID select o);
foreach (myobject obj in myobjects)
{
//perform action on obj here
}
答案 0 :(得分:0)
我会快速处理ID的快照 - 作为交易 - 然后以您今天正在做的方式处理该列表。
除了实现不更改样本中间流的目标之外,这还使您能够将解决方案扩展到跟踪每个项目的处理状态。对于长时间运行的过程,这对于进度报告重启/重试功能等非常有用。
答案 1 :(得分:0)
这取决于您的确切实施。
对数据库执行查询后,查询结果不会更改(假设您没有使用延迟加载)。为了确保这一点,您可以在检索查询结果后处理上下文 - 这有效地“切断了检索到的数据与该数据库之间的连线”。
延迟加载会导致混合“初始”和“新”数据;但是一旦检索到数据,它将成为一个固定的快照,不易受到更新的影响。
你提到这是一个漫长的过程;这意味着可能涉及非常大量的数据。如果您无法完全检索要处理的所有数据(由于内存限制或其他瓶颈),那么您可能无法确保您正在处理原始数据。在执行查询之前,结果不会得到修复,查询执行之前的任何更新都将显示在结果中。
答案 2 :(得分:0)
我认为最好的办法是更改应用程序的逻辑,以便当“循环”逻辑确定是否应该进行另一次交互或退出时,您可以利用机会将新添加的项目加载到列表中。看下面的伪代码:
var repo = new Repository();
while (repo.HasMoreItemsToProcess())
{
var entity = repo.GetNextItem();
}
如果这是有道理的,请告诉我。
答案 3 :(得分:0)
确保发生这种情况的最简单方法 - 如果数据本身不是太大 - 是将您从数据库中检索的数据转换为List&lt;&gt;,例如,像这样的东西(从我的随机抽取)当前项目):
var sessionIds = room.Sessions.Select(s => s.SessionId).ToList();
然后遍历列表,而不是通过IEnumerable&lt;&gt;否则将被退回。将其转换为列表会触发枚举,然后将所有结果抛出到内存中。
如果有太多数据无法容纳到内存中,并且您需要坚持使用IEnumerable&lt;&gt;,那么您的问题的答案取决于各种数据库和连接设置。