3

我创建了几个自定义活动来更新我的数据库中的表(在本例中为 SQL Server Compact),使用带有 POCO 的实体框架 4。

如果我在 WF4 TransactionScope 活动中放置了多个这些,我会遇到问题:EF 在第一个活动完成后释放数据库连接,并且当下一个数据库活动尝试进行数据库更新时,会建立一个新连接向上。此时抛出异常。

System.Activities.WorkflowApplicationAbortedException : The workflow has been aborted.
 ----> System.Data.EntityException : The underlying provider failed on Open.
 ----> System.InvalidOperationException : The connection object can not be enlisted in transaction scope.

我是否必须在整个事务范围内保持 EF 连接打开?我怎样才能做到这一点?为此创建一个明确的自定义活动,还是有标准方法?

我当前的解决方法是这样的:我创建了一个新的代码活动来创建我们的 ObjectContext 并明确调用 dbContext.Connection.Open()。它返回 ObjectContext,然后将其保存在工作流变量中。那个作为 InArgument<> 传递给所有与 DB 相关的活动。在我的数据库活动中,如果传入了这个 ObjectContext,我会使用它,否则我会创建一个新的。

这确实有效,但我对这个解决方案不满意:它需要新的 InArgument 用于每个与 ​​DB 相关的活动。在工作流设计器中,我必须在事务范围内插入特殊的 OpenDatabaseConnection 活动,然后确保将正确的变量传递到所有 DB 活动中。这似乎非常不雅且容易出错,特别是如果其他团队成员必须使用这些数据库活动。

有什么更好的方法来处理这个问题?

4

1 回答 1

1

问题在于,当您在同一事务范围内打开第二个连接时,会尝试将该事务提升为分布式事务(即使由于您连接到同一个数据库而没有任何分布式事务)。SQL Server CE 不支持这种情况。

我要做的是创建一个自定义的“容器”活动来打开(和关闭)连接并使其可用于子活动。这仍然不是最佳的,但至少你不再需要传递InArgument's 。您将获得以下活动树:

TransactionScope
    InitializeConnection
        Sequence
            CustomDataActivity1
            CustomDataActivity2
            CustomDataActivity3

InitializeConnection是一个NativeActivity用于NativeActivityContext.Properties将连接(或ObjectContext)暴露给子活动的。

确保实施正确的错误处理,以确保始终关闭连接。

注意:完整的 SQL Server 仅通过称为MSDTC(Microsoft 分布式事务协调器)的 Windows 服务支持分布式事务。您可以在“本地服务”中找到这个。由于 SQL Server CE 是一个应该能够完全独立运行的数据库,因此它不依赖于 MSDTC 是有道理的。因此它不支持分布式事务。

于 2012-10-08T12:27:25.937 回答