正在当前事务中加入SQL Server CLR集成

问题描述

| 我正在尝试在SQL Server中使用CLR集成来处理对外部文件的访问,而不是将其内部存储为BLOB。我正在尝试找出使我的代码加入当前SQL事务所需的模式。我想我将从最简单的场景开始,删除现有行,因为插入/更新场景会更复杂。
[SqlProcedure]
public static void DeleteStoredImages(SqlInt64 DocumentID)
{
    if (DocumentID.IsNull)
        return;

    using (var conn = new SqlConnection(\"context connection=true\"))
    {
        conn.Open();

        string FaceFileName,RearFileName;
        int Offset,Length;
        GetFileLocation(conn,DocumentID.Value,true,out FaceFileName,out Offset,out Length);
        GetFileLocation(conn,false,out RearFileName,out Length);

        new DeleteTransaction().Enlist(FaceFileName,RearFileName);

        using (var comm = conn.CreateCommand())
        {
            comm.CommandText = \"DELETE FROM ImagesStore WHERE DocumentID = \" + DocumentID.Value;
            comm.ExecuteNonQuery();
        }
    }
}

private class DeleteTransaction : IEnlistmentNotification
{
    public string FaceFileName { get; set; }
    public string RearFileName { get; set; }
    public void Enlist(string FaceFileName,string RearFileName)
    {
        this.FaceFileName = FaceFileName;
        this.RearFileName = RearFileName;
        var trans = Transaction.Current;
        if (trans == null)
            Commit(null);
        else
            trans.EnlistVolatile(this,EnlistmentOptions.None);
    }
    public void Commit(Enlistment enlistment)
    {
        if (FaceFileName != null && File.Exists(FaceFileName))
        {
            File.Delete(FaceFileName);
        }
        if (RearFileName != null && File.Exists(RearFileName))
        {
            File.Delete(RearFileName);
        }
    }

    public void InDoubt(Enlistment enlistment)
    {
    }

    public void Prepare(PreparingEnlistment preparingEnlistment)
    {
        preparingEnlistment.Prepared();
    }

    public void Rollback(Enlistment enlistment)
    {
    }
}
当我实际尝试运行此命令时,出现以下异常:
A .NET Framework error occurred during execution of user defined routine or aggregate \'DeleteStoredImages\': 
System.Transactions.TransactionException: The operation is not valid for the state of the transaction. ---> System.Transactions.TransactionPromotionException: MSDTC on server \'BD009\' is unavailable. ---> System.Data.SqlClient.SqlException: MSDTC on server \'BD009\' is unavailable.
System.Data.SqlClient.SqlException: 
   at System.Data.SqlServer.Internal.StandardEventSink.HandleErrors()
   at System.Data.SqlServer.Internal.ClrLevelContext.SuperiorTransaction.Promote()
System.Transactions.TransactionPromotionException: 
   at System.Data.SqlServer.Internal.ClrLevelContext.SuperiorTransaction.Promote()
   at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
   at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
System.Transactions.TransactionException: 
   at System.Transactions.TransactionState.EnlistVolatile(InternalTransaction tx,IEnlistmentNotification enlistmentNotification,EnlistmentOptions enlistmentOptions,Transaction atomicTransaction)
   at System.Transactions.TransactionStateSubordinateActive.EnlistVolatile(InternalTransaction tx,Transaction atomicTransaction)
   at System.Transactions.Transaction.EnlistVolatile(IEnlistmentNotification enlistmentNotification,EnlistmentOptions enlistmentOptions)
   at ExternalImages.StoredProcedures.DeleteTransaction.Enlist(String FaceFileName,String RearFileName)
   at ExternalImages.StoredProcedures.DeleteStoredImages(SqlInt64 DocumentID)
. User transaction,if any,will be rolled back.
The statement has been terminated.
谁能解释我做错了什么,或者为我指出正确做事的例子?     

解决方法

希望您现在已经解决了此问题,但是如果其他任何人也遇到类似的问题:收到的错误消息表明您需要在
BD009
机器(可能是您自己的机器)上启动Distributed Transaction Coordinator服务。     ,@Aasmund关于
Distributed Transaction Coordinator
的答案可能会解决上述问题,但这仍然使您处于非理想状态:您正在将一笔交易锁定,该交易将
ImagesStore
表(即使只是
RowLock
)锁定为两个文件系统操作?并且您需要在该函数之外进行
BEGIN
COMMIT
事务(因为所提供的代码未处理该事务)。 我将这两部分分开: 步骤1:从表格中删除行 然后,如果没有出错, 步骤2:删除档案 在步骤1成功但随后步骤2由于任何原因失败的情况下,请执行以下一项或两项操作: 返回错误的状态代码,并在尝试删除状态表中的文件时跟踪哪个ѭ8错误。您可以使用它来手动删除文件和/或调试发生错误的原因。 创建一个可以定期运行以查找和删除未引用文件的进程。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...