【问题标题】:new objects added during long loop长循环期间添加的新对象
【发布时间】:2011-11-02 15:44:57
【问题描述】:

我们目前有一个作为 Windows 服务运行的生产应用程序。很多时候,这个应用程序最终会陷入一个可能需要几个小时才能完成的循环。我们正在使用 .net 4.0 的实体框架进行数据访问。

我正在寻找确认,如果我们将新数据加载到系统中,在此循环初始化后,它不会导致项目被添加到循环本身。当循环初始化时,我们正在寻找那一刻的数据。虽然我相对确定这将完全像使用 ADO 并对数据执行循环(循环仅循环通过初始化时存在的数据),但我正在寻找同事的确认。

提前感谢您的帮助。

//更新:这里有一些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
}

【问题讨论】:

  • 杰夫,你不能肯定地说,这取决于代码是如何编写的,而不是框架。大多数(不是全部)程序员编写批处理以在流程开始时查询所有数据。但是,程序有可能(尽管不太可能)在整个操作过程中查询数据库。一个明确的答案需要通过代码。

标签: c# .net frameworks entity


【解决方案1】:

这取决于您的精确实施。

一旦对数据库执行了查询,查询的结果就不会改变(假设您没有使用延迟加载)。为确保这一点,您可以在检索查询结果后处理上下文——这有效地“切断了检索数据与该数据库之间的联系”。

延迟加载可能会导致“初始”数据和“新”数据混合在一起;然而,一旦数据被检索到,它将成为一个固定的快照,并且不易被更新。

您提到这是一个长期运行的过程;这意味着可能涉及的数据量非常大。如果您无法完全检索所有要处理的数据(由于内存限制或其他瓶颈),那么您可能无法确保您正在处理原始数据。在执行查询之前,结果不会固定,并且查询执行之前的任何更新都将出现在结果中。

【讨论】:

  • 这就是答案,我需要看看实现 IEnumerable 是否与执行 ToList() 一样。由于 EF 中默认开启延迟加载
  • 我还发现确认实现 IEnumerable 消除了延迟加载部分并将结果加载到内存中。所以答案是,我在集合上方的代码将保持不变。
  • 是的,根据经验,IQueryable 是您需要最小心的界面
【解决方案2】:

我认为您最好的选择是更改应用程序的逻辑,以便当“循环”逻辑确定它是否应该进行另一次交互或退出时,您可以借此机会将新添加的项目加载到列表中。见下面的伪代码:

var repo = new Repository();
while (repo.HasMoreItemsToProcess())
{
   var entity = repo.GetNextItem();
}

让我知道这是否有意义。

【讨论】:

  • 您好,感谢您的建议,但我担心的是我不希望处理新对象。如果我需要检查新对象然后插入它们,您的代码将是完美的。问题是我不确定实体框架在遍历枚举时是如何工作的。如果它在每个循环中限定集合,或者它只是按照最初初始化的方式维护集合。
  • 明白了。它将您在 Linq 中编写的任何内容转换为 SQL 查询,因此我可以想象,每当您针对上下文执行查询时,它都不会“侦听”正在添加的新行。
  • (这就是为什么我建议在 EF 之外添加你自己的抽象层)
【解决方案3】:

确保发生这种情况的最简单方法 - 如果数据本身不是太大 - 是将您从数据库检索到的数据转换为 List,例如,类似这样的东西(从我当前的项目):

var sessionIds = room.Sessions.Select(s => s.SessionId).ToList();

然后遍历列表,而不是遍历否则会返回的 IEnumerable。将其转换为列表会触发枚举,然后将所有结果都扔到内存中。

如果有太多数据无法放入内存,并且您需要坚持使用 IEnumerable,那么您的问题的答案取决于各种数据库和连接设置。

【讨论】:

    【解决方案4】:

    我会拍一张要处理的 ID 的快照——快速地作为一个事务处理——然后以你今天正在做的方式处理该列表。

    除了实现不中途更改示例的目标之外,这还使您能够扩展解决方案以跟踪每个项目的处理状态。对于长时间运行的进程,这对于进度报告重启/重试功能等非常有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-31
      • 1970-01-01
      • 1970-01-01
      • 2018-05-19
      • 2021-09-28
      • 2014-05-26
      • 1970-01-01
      • 2016-03-17
      相关资源
      最近更新 更多