【问题标题】:Initiating a TransactionScope from Excel VBA?从 Excel VBA 启动 TransactionScope?
【发布时间】:2014-07-25 18:51:48
【问题描述】:

我有一些现有的 c# 代码,我想通过 com 互操作公开,以便可以从 Excel VBA 调用它。由于我将执行许多嵌套的批量更新操作,我需要支持事务,并且为了最大限度地减少 c# 级别所需的重构,我想使用 TransactionScope 方法:

使用事务范围实现隐式事务
http://msdn.microsoft.com/en-us/library/ms172152.aspx

TransactionScope 类提供了一种简单的方法来标记一个块 代码作为参与交易,而无需您 与交易本身进行交互。事务范围可以选择 并自动管理环境事务。由于其易于 使用和效率,建议您使用 开发事务应用程序时的 TransactionScope 类。

此外,您无需使用 交易。任何 System.Transactions 资源管理器(例如 SQL Server 2005) 可以检测环境事务的存在 由作用域创建并自动登记。

我的问题是:是否可以在 VBA 代码中初始化 TransactionScope(或通过 COM 互操作调用 ac# 方法来实例化并返回一个 TransactionScope 对象),然后继续调用其他各种c# 对象通过 COM 互操作,会自动参与单一根事务?

【问题讨论】:

  • 不,你绝对不能在 VBA 中这样做。
  • 你能详细说明一下吗(希望我不是要求你证明否定)
  • 我已经删除了我的答案,因为我认为我们在理解 C# 中的 TransactionScope 以及 VBA 中的含义不一致。 ADODB 实现了在事务期间回滚任何更改的机制,但是您不能将任何 VBA 代码块包装在 TransactionScope 中并在事务失败时将其回滚...

标签: c# sql-server vba excel com-interop


【解决方案1】:

我认为您的方法没有问题。您在 VBA 中没有 using,因此您必须通过

来模拟它
  • 使用错误处理程序和
  • 要非常小心,不要在没有以一种或另一种方式处理 TransactionScope 的情况下离开方法。

例如,假设在您的 C# 应用程序中,您提供了以下方法:

public TransactionScope BeginTransactionScope()
{
    return new TransactionScope();
}

public void CommitTransactionScope(TransactionScope scope)
{
    scope.Complete();
    scope.Dispose();  // simulates leaving the using { ... } scope
}

public void RollbackTransactionScope(TransactionScope scope)
{
    scope.Dispose();  // simulates leaving the using { ... } scope
}

// Does some work using Connections and maybe nested scopes
public void DoSomeWork1() { ... }
public void DoSomeWork2() { ... }
public void DoSomeWork3() { ... }

您编译您的 C# DLL 并通过 COM 互操作将其提供给 Excel VBA。在 VBA 中,您可以按如下方式运行方法:

Private Sub MySub()

    On Error Goto MyErrorHandler

    ...
    Dim scope As Object
    Set scope = myCsObject.BeginTransactionScope()
    ...
    myCsObject.DoSomeWork1
    ...
    myCsObject.DoSomeWork2
    ...
    myCsObject.DoSomeWork3
    ...
    myCsObject.CommitTransactionScope scope
    Set scope = Nothing
    ...

    Exit Sub

MyErrorHandler:
    If Not (scope Is Nothing) Then
        myCsObject.RollbackTransactionScope scope
    End If
    ' Remainder of your error handler goes here
    ...
End Sub

但请注意,您使用 VBA 代码 执行的任何数据访问(在 DoSomeWork 调用之间)都将在事务范围之外,因为 TransactionScope 与经典的 ADO 或 DAO。

【讨论】:

  • 对不起,我可能在这里误解了一些东西,但所有这一切的意义是什么,因为如果您使用 C# 来处理事务并只是从 VBA 显式调用它。您也可以在 C# 中处理整个事务过程,并且只需一个方法来返回结果。为什么要将它全部暴露给 VBA,因为它可以通过 C# 轻松处理?
  • @mehow: 1. 感谢您发现错字,已修复。 2. 也许他需要在各种DoSomeWork 调用之间执行VBA 代码?无论如何,这是一个很好的问题,但它可能更适合针对 OP 而不是针对我。
  • 是的,你在 VBA 中没有 using,但你有 with <object> end with。它的工作方式与 C# 中的 using 不同,但我猜它们在某种程度上相关。我的观点是,您不能在 VBA 中设置 TransactionScope,因为 VBA 使用 VB6 虚拟机作为运行时,并且它不允许您回滚自己的代码(如果有任何意义)(抱歉难以解释)。
  • @mehow: True,usingWith 相似之处在于它们都创建了某种范围,但 using 在其范围末尾调用 Dispose,而 @987654333 @ 仅提供访问字段和方法的词法快捷方式。
  • 是的,但是您可以创建一个实现 IDispose 的自定义类,并且当所有对对象的引用都空闲时,它最终会被调用(VBA 使用引用计数),而您可以创建自己的实例TransactionScopeWrapper 原始 TransactionScope 的类包装器,但不幸的是,System.TransactionScope 在 COM 不可见。
猜你喜欢
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 2015-11-22
  • 2016-05-12
  • 1970-01-01
  • 2018-05-19
  • 2012-03-14
相关资源
最近更新 更多