如何使用Entity Framework处理长时间运行的操作?

时间:2015-04-27 17:27:08

标签: c# entity-framework

我们的团队正在开发一种机器,该机器将在托盘上执行物理过程,该托盘可容纳样品瓶。物理过程大约需要1.5小时。托盘和相关的样品瓶是使用实体框架从数据库加载的实体。当进程运行时,设备将更新实体的值。这些变化可能会分开几分钟或几秒钟。在某些步骤结束时,相隔10到45分钟,我们希望将这些实体保存回数据库,然后继续。

让实体框架上下文打开1.5小时是否可以接受?我可以使用该上下文在该时间段内多次进行更改并保存实体吗?如果没有,处理这个问题的最佳方法是什么?

到目前为止的一些想法:

  • 我们可以使用附加/分离功能。这应该允许我们对上下文之外的实体进行更改,然后创建新上下文并在我们想要保存时附加实体,然后将其分离以继续工作。
  • 每次我们想要更改其中一个实体时,我们都可以创建一个新的上下文。但我不认为每次做出改变都要保存。
  • 我们可以将实体复制到业务对象,并在那里进行更改。然后,当我们想要保存时,我们将打开一个上下文并将更改复制到实体中,并保存。

3 个答案:

答案 0 :(得分:3)

2和3的组合将是理想的。

首先,不要让上下文一次打开几个小时。您可以通过配置执行此操作,但考虑到您正在执行90分钟的操作并且打开连接大约需要3毫秒,这只会浪费资源。

所以只需根据需要创建一个上下文。接下来,请记住,虽然您打开上下文来收集数据或维护状态,但如果数据尚未准备好存储,则实际上并不需要保存数据。你可以在本地存储它。

这是第3步进入的地方,带有本地内存。基本上你应该在附加事件处理程序的情况下将它保存在本地内存中。随着本地副本的更改,如果在某个可接受的时间窗口内发生了更改,请让数据库更新。

答案 1 :(得分:2)

  

让实体框架上下文打开1.5小时是否可以接受?

更新:根据您链接的资源,如果您允许EF管理连接的打开和关闭,它将尽可能晚地打开连接并尽早关闭它,以便相对昂贵的数据库连接可以返回连接池。如果手动管理数据库连接,则连接仅在上下文存在期间保持打开状态。

  

在某些步骤结束时,相隔10到45分钟,我们希望将这些实体保存回数据库,然后继续。

请注意,如果客户端因任何原因崩溃,则内存中保留的更改将会丢失。在确定您是否真的想要等待那么久之后,请考虑这种影响。

如果确定这是并且仍将是一个或只有少数客户写入专用数据库的架构,我会选择尽可能简单地保持代码...交易资源效率低下并不重要在这种非常具体的情况下,程序员错误的可能性较小。

答案 2 :(得分:1)

据我所知,您希望批量保存数据,如果批量整体不成功,则保存单个值无效。

由于资源不是瓶颈而且这是一个专用系统,因此上下文相对较长并不重要,因此我会使用每批上下文。上下文收集数据并通过一次SaveChanges调用结束每个批处理,这会自动将一个批处理保存在一个数据库事务中。粗略地说,代码看起来像这样:

do
{
    // Start of a new batch.
    using(var db = new MyContext())
    {
        // Collect data into the context
        ...
        SaveChanges();
    }
} while (....); // While there are new batches

数据库连接将在需要时打开和关闭。 SaveChanges将执行此操作,但也可以在中间执行任何其他数据库交互。 EF永远不会让连接打开的时间超过必要的时间。