Hangfire:Azure SQL:添加新作业失败

时间:2017-01-13 10:22:04

标签: distributed-transactions hangfire azure-sql-database

获得以下错误

内部异常:“对象引用未设置为对象的实例。” 堆栈跟踪: 在System.Transactions.Transaction.GetPromotedToken()

错误来自行connection.EnlistTransaction(Transaction.Current);在下面的代码中,即使我在连接字符串中设置了enlist = false。

   `internal T UseTransaction<T>([InstantHandle] Func<DbConnection, DbTransaction, T> func, IsolationLevel? isolationLevel)
    {
     #if NETFULL
        using (var transaction = CreateTransaction(isolationLevel ?? _options.TransactionIsolationLevel))
        {
            var result = UseConnection(connection =>
            {
                connection.EnlistTransaction(Transaction.Current);
                return func(connection, null);
            });

            transaction.Complete();

            return result;
        }
}`

当我们设置enlist = true时,我们在line connection.Open();来自以下代码

    internal DbConnection CreateAndOpenConnection()
    {
        if (_existingConnection != null)
        {
            return _existingConnection;
        }

        var connection = new SqlConnection(_connectionString);
        connection.Open();

        return connection;
    }

这两种方法都存在于Hangfire.SqlServer.SqlServerStorage类

连接到本地数据库(SQL Server 2014)时,相同的代码可以正常工作。

登陆讨论WCF Transaction against Azure SQL DB,不确定它是否与此问题相关。

修改

HangFire配置

GlobalConfiguration.Configuration.UseSqlServerStorage(
                Database.ConnectionString,
                new SqlServerStorageOptions
                {
                    QueuePollInterval = TimeSpan.FromSeconds(10),
                    PrepareSchemaIfNecessary = true
                });

工作入队

BackgroundJob.Enqueue(() => Update(connectionToken, intFileUniqueId));

请帮忙。 提前谢谢。

1 个答案:

答案 0 :(得分:1)

发现了这个问题。调用方法来排队作业是在内部事务中,它以某种方式导致分发事务,而Azure SQL不支持它。

请考虑以下代码:

    public override void UpdateFile(int intUniqueId)
    {
        using (var scope = GetTransactionScope(...))
        {
             QueueJob<Updater>(x => x.Update(token, intUniqueId));
            scope.Complete();
        }
    }


    private static void QueueJob<T>(Expression<Action<T>> action)
    {
            BackgroundJob.Enqueue(action);
    }

在callee方法中删除事务范围有效。 我正在检查交易范围的必要性,如果不需要,我会删除它。!!!