缺少引用 OLEDB 连接类型的库

2024-03-02

我从以下代码中得到了SSIS 团队博客 http://blogs.msdn.com/b/mattm/archive/2008/08/22/accessing-oledb-connection-managers-in-a-script.aspx转换 OLEDB 连接类型,以便 AcquireConnection () 方法可以使用它。现在我不确定为什么 Dts.Connections 部分不起作用。我不知道我必须添加哪个库才能使其工作。我几乎添加了最重要的部分,包括 Dts.RuntimeWrap。如果您需要有关该问题的更多信息,请告诉我。

ConnectionManager cm = Dts.Connections["oledb"];
Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100 cmParams = cm.InnerObject as Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100;
OleDbConnection conn = cmParams.GetConnectionForSchema() as OleDbConnection;

EDIT以下是该组件的完整代码。

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Microsoft.SqlServer.Dts.Runtime;
using System.Data.OleDb;
using System.Data.Common;
using System.Linq;
using System.Configuration;
using System.Collections;

//using System.Data.OleDb;

namespace AOC.SqlServer.Dts.Tasks
{

    [DtsTask(
        DisplayName = "Custom Logging Task",
        Description = "Writes logging info into a table")]
    public class CustomLoggingTask : Task
    {

        private string _packageName;
        private string _taskName;
        private string _errorCode;
        private string _errorDescription;
        private string _machineName;
        private double _packageDuration;

        private string _connectionName;
        private string _eventType;
        private string _executionid;
        private DateTime _handlerdatetime;
        private string _uid;
        public string ConnectionName
        {
            set
            {
                _connectionName = value;
            }
            get
            {
                return _connectionName;
            }
        }


        public string Event
        {
            set
            {
                _eventType = value;
            }
            get
            {
                return _eventType;
            }
        }

public override DTSExecResult Validate(Connections connections, VariableDispenser variableDispenser, IDTSComponentEvents componentEvents, IDTSLogging log)
        {
            const string METHOD_NAME = "CustomLoggingTask-Validate";

            try
            {

                if (string.IsNullOrEmpty(_eventType))
                {
                    componentEvents.FireError(0, METHOD_NAME, "The event property must be specified", "", -1);
                    return DTSExecResult.Failure;
                }


                if (string.IsNullOrEmpty(_connectionName))
                {
                    componentEvents.FireError(0, METHOD_NAME, "No connection has been specified", "", -1);
                    return DTSExecResult.Failure;
                }


                //SqlConnection connection = connections[_connectionName].AcquireConnection(null) as SqlConnection;
                DbConnection connection = connections[_connectionName].AcquireConnection(null) as DbConnection;

                ConnectionManager cm = Dts.Connections["oledb"];
                Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100 cmParams = cm.InnerObject as Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100;
                OleDbConnection conn = cmParams.GetConnectionForSchema() as OleDbConnection;



                if (connection == null)
                {
                    componentEvents.FireError(0, METHOD_NAME, "The connection is not a valid ADO.NET connection", "", -1);
                    return DTSExecResult.Failure;
                }

               if (!variableDispenser.Contains("System::SourceID"))
                {
                    componentEvents.FireError(0, METHOD_NAME, "No System::SourceID variable available. This task can only be used in an Event Handler", "", -1);
                    return DTSExecResult.Failure;
                }

                return DTSExecResult.Success;
            }
            catch (Exception exc)
            {
                componentEvents.FireError(0, METHOD_NAME, "Validation Failed: " + exc.ToString(), "", -1);
                return DTSExecResult.Failure;
            }
        }


public override DTSExecResult Execute(Connections connections, VariableDispenser variableDispenser, IDTSComponentEvents componentEvents, IDTSLogging log, object transaction)
       {
          try
            {
                string commandText =
@"INSERT INTO SSISLog (EventType, PackageName, TaskName, EventCode, EventDescription, PackageDuration, Host, ExecutionID, EventHandlerDateTime,UID)
VALUES (@EventType, @PackageName, @TaskName, @EventCode, @EventDescription, @PackageDuration, @Host, @Executionid, @handlerdatetime,@uid)";

                ReadVariables(variableDispenser);
                DbConnection connection = connections[_connectionName].AcquireConnection(transaction) as DbConnection;
                //SqlConnection connection = (SqlConnection)connections[_connectionName].AcquireConnection(transaction);
                DbCommand command = null;
                //using (SqlCommand command = new SqlCommand())
                if (connection is SqlConnection)
                    command = new SqlCommand();
                else if (connection is OleDbConnection)
                    command = new OleDbCommand();

                {
                    command.CommandText = commandText;
                    command.CommandType = CommandType.Text;
                    command.Connection = connection;

                    command.Parameters.Add(new SqlParameter("@EventType", _eventType));
                    command.Parameters.Add(new SqlParameter("@PackageName", _packageName));
                    command.Parameters.Add(new SqlParameter("@TaskName", _taskName));
                    command.Parameters.Add(new SqlParameter("@EventCode", _errorCode ?? string.Empty));
                    command.Parameters.Add(new SqlParameter("@EventDescription", _errorDescription ?? string.Empty));
                    command.Parameters.Add(new SqlParameter("@PackageDuration", _packageDuration));
                    command.Parameters.Add(new SqlParameter("@Host", _machineName));
                    command.Parameters.Add(new SqlParameter("@ExecutionID", _executionid));
                    command.Parameters.Add(new SqlParameter("@handlerdatetime", _handlerdatetime));
                    command.Parameters.Add(new SqlParameter("@uid", _uid));
                    command.ExecuteNonQuery();
                }
                connection.Close();
                return DTSExecResult.Success;

            }
            catch (Exception exc)
            {
                componentEvents.FireError(0, "CustomLoggingTask-Execute", "Task Errored: " + exc.ToString(), "", -1);
                return DTSExecResult.Failure;
            }

        }


        private void ReadVariables(VariableDispenser variableDispenser)
        {
            variableDispenser.LockForRead("System::StartTime");
            variableDispenser.LockForRead("System::PackageName");
            variableDispenser.LockForRead("System::SourceName");
            variableDispenser.LockForRead("System::MachineName");
            variableDispenser.LockForRead("System::ExecutionInstanceGUID");
            variableDispenser.LockForRead("System::EventHandlerStartTime");
            variableDispenser.LockForRead("User::UID");
            bool includesError = variableDispenser.Contains("System::ErrorCode");
            if (includesError)
            {
                variableDispenser.LockForRead("System::ErrorCode");
                variableDispenser.LockForRead("System::ErrorDescription");
            }

            Variables vars = null;
            variableDispenser.GetVariables(ref vars);

            DateTime startTime = (DateTime)vars["System::StartTime"].Value;
            _packageDuration = DateTime.Now.Subtract(startTime).TotalSeconds;
            _packageName = vars["System::PackageName"].Value.ToString();
            _taskName = vars["System::SourceName"].Value.ToString();
            _machineName = vars["System::MachineName"].Value.ToString();
            _executionid = vars["System::ExecutionInstanceGUID"].Value.ToString();
            _handlerdatetime = (DateTime)vars["System::EventHandlerStartTime"].Value;
            _uid = vars["User::UID"].Value.ToString();
            if (includesError)
            {
                _errorCode = vars["System::ErrorCode"].Value.ToString();
                _errorDescription = vars["System::ErrorDescription"].Value.ToString();
            }

            // release the variable locks.
            vars.Unlock();

            // reset the dispenser
            variableDispenser.Reset();
        }
    }

}

通过您发布的代码,我终于弄清楚了您想要完成的任务。

为了让它发挥作用,我做了这些事情:

A)您收到的编译错误:

"Error 1 The type or namespace name 'Connections' does not exist in the namespace 'AOC.SqlServer.Dts' (are you missing an assembly reference?)"

只是因为你试图获得的方式oledb连接管理器:

ConnectionManager cm = Dts.Connections["oledb"];

The Dts对象是脚本任务组件中可用的工具。您应该将该行替换为:

ConnectionManager cm = connections["oledb"];

我在你的代码中看到你访问了Connection Manager这样看来,也许这是你刚刚留下的东西。

B)要验证连接管理器是 ADO.NET 连接管理器还是 OLEDB 连接管理器,请更改这部分代码:

DbConnection connection = connections[_connectionName].AcquireConnection(null) as DbConnection;

ConnectionManager cm = Dts.Connections["oledb"];
Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100 cmParams = cm.InnerObject as Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100;
OleDbConnection conn = cmParams.GetConnectionForSchema() as OleDbConnection;

if (connection == null)
{
    componentEvents.FireError(0, METHOD_NAME, "The connection is not a valid ADO.NET connection", "", -1);
    return DTSExecResult.Failure;
}

首先,在类级别添加一个私有变量来存储连接:

private DbConnection _connection;

然后,修改验证以检查连接是否为 ADO.NET,如果不是,则检查它是否为 OLEDB:

_connection = connections[_connectionName].AcquireConnection(null) as DbConnection;

if (_connection == null)
{
    ConnectionManager cm = connections[_connectionName];
    Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100 cmParams = cm.InnerObject as Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100;
    _connection = cmParams.GetConnectionForSchema() as OleDbConnection;

    if (_connection == null)
    {
        componentEvents.FireError(0, METHOD_NAME, "The connection is not a valid ADO.NET or OLEDB connection", "", -1);
        return DTSExecResult.Failure;
    }
}

请注意,我替换了硬编码"oledb"_connectionName变量,并且还修改了错误字符串_connection在这两种情况下都为空。

C)要使用 OLEDB 提供程序执行命令,需要进行以下更改:

  • 使用新的_connection变量,保存先前检索到的连接。
  • 命令中添加的参数必须是OleDbParameter代替SqlParameter.
  • The OLE DB .NET 提供程序 http://msdn.microsoft.com/en-us/library/system.data.oledb.oledbcommand.parameters.aspx不支持命名参数。所以VALUES部分于INSERT语句命令需要修改才能使用?.

D)这是完整的工作代码:

using System;
using System.Data;
using System.Data.Common;
using System.Data.OleDb;
using System.Data.SqlClient;
using Microsoft.SqlServer.Dts.Runtime;

//using System.Data.OleDb;

namespace AOC.SqlServer.Dts.Tasks
{
    [DtsTask(
        DisplayName = "Custom Logging Task",
        Description = "Writes logging info into a table")]
    public class CustomLoggingTask : Task
    {
        private string _packageName;
        private string _taskName;
        private string _errorCode;
        private string _errorDescription;
        private string _machineName;
        private double _packageDuration;

        private string _connectionName;
        private string _eventType;
        private string _executionid;
        private DateTime _handlerdatetime;
        private string _uid;

        public string ConnectionName
        {
            set { _connectionName = value; }
            get { return _connectionName; }
        }

        public string Event
        {
            set { _eventType = value; }
            get { return _eventType; }
        }

        private DbConnection _connection;

        public override DTSExecResult Validate(Connections connections, VariableDispenser variableDispenser, IDTSComponentEvents componentEvents, IDTSLogging log)
        {
            const string METHOD_NAME = "CustomLoggingTask-Validate";

            try
            {
                if (string.IsNullOrEmpty(_eventType))
                {
                    componentEvents.FireError(0, METHOD_NAME, "The event property must be specified", "", -1);
                    return DTSExecResult.Failure;
                }

                if (string.IsNullOrEmpty(_connectionName))
                {
                    componentEvents.FireError(0, METHOD_NAME, "No connection has been specified", "", -1);
                    return DTSExecResult.Failure;
                }

                //SqlConnection connection = connections[_connectionName].AcquireConnection(null) as SqlConnection;
                _connection = connections[_connectionName].AcquireConnection(null) as DbConnection;

                if (_connection == null)
                {
                    ConnectionManager cm = connections[_connectionName];
                    Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100 cmParams = cm.InnerObject as Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100;
                    _connection = cmParams.GetConnectionForSchema() as OleDbConnection;

                    if (_connection == null)
                    {
                        componentEvents.FireError(0, METHOD_NAME, "The connection is not a valid ADO.NET or OLEDB connection", "", -1);
                        return DTSExecResult.Failure;
                    }
                }

                if (!variableDispenser.Contains("System::SourceID"))
                {
                    componentEvents.FireError(0, METHOD_NAME, "No System::SourceID variable available. This task can only be used in an Event Handler", "", -1);
                    return DTSExecResult.Failure;
                }

                return DTSExecResult.Success;
            }
            catch (Exception exc)
            {
                componentEvents.FireError(0, METHOD_NAME, "Validation Failed: " + exc.ToString(), "", -1);
                return DTSExecResult.Failure;
            }
        }

        public override DTSExecResult Execute(Connections connections, VariableDispenser variableDispenser, IDTSComponentEvents componentEvents, IDTSLogging log, object transaction)
        {
            try
            {
                string commandText = null;

                ReadVariables(variableDispenser);
                //DbConnection connection = connections[_connectionName].AcquireConnection(transaction) as DbConnection;
                //SqlConnection connection = (SqlConnection)connections[_connectionName].AcquireConnection(transaction);
                DbCommand command = null;

                //using (SqlCommand command = new SqlCommand())
                if (_connection is SqlConnection)
                {
                    commandText = @"INSERT INTO SSISLog (EventType, PackageName, TaskName, EventCode, EventDescription, PackageDuration, Host, ExecutionID, EventHandlerDateTime,UID)
                                    VALUES (@EventType, @PackageName, @TaskName, @EventCode, @EventDescription, @PackageDuration, @Host, @Executionid, @handlerdatetime,@uid)";

                    command = new SqlCommand();

                    command.Parameters.Add(new SqlParameter("@EventType", _eventType));
                    command.Parameters.Add(new SqlParameter("@PackageName", _packageName));
                    command.Parameters.Add(new SqlParameter("@TaskName", _taskName));
                    command.Parameters.Add(new SqlParameter("@EventCode", _errorCode ?? string.Empty));
                    command.Parameters.Add(new SqlParameter("@EventDescription", _errorDescription ?? string.Empty));
                    command.Parameters.Add(new SqlParameter("@PackageDuration", _packageDuration));
                    command.Parameters.Add(new SqlParameter("@Host", _machineName));
                    command.Parameters.Add(new SqlParameter("@ExecutionID", _executionid));
                    command.Parameters.Add(new SqlParameter("@handlerdatetime", _handlerdatetime));
                    command.Parameters.Add(new SqlParameter("@uid", _uid));
                }
                else if (_connection is OleDbConnection)
                {
                    commandText = @"INSERT INTO SSISLog (EventType,PackageName,TaskName,EventCode,EventDescription,PackageDuration,Host,ExecutionID,EventHandlerDateTime,UID)
                                    VALUES (?,?,?,?,?,?,?,?,?,?)";

                    command = new OleDbCommand();

                    command.Parameters.Add(new OleDbParameter("@EventType", _eventType));
                    command.Parameters.Add(new OleDbParameter("@PackageName", _packageName));
                    command.Parameters.Add(new OleDbParameter("@TaskName", _taskName));
                    command.Parameters.Add(new OleDbParameter("@EventCode", _errorCode ?? string.Empty));
                    command.Parameters.Add(new OleDbParameter("@EventDescription", _errorDescription ?? string.Empty));
                    command.Parameters.Add(new OleDbParameter("@PackageDuration", _packageDuration));
                    command.Parameters.Add(new OleDbParameter("@Host", _machineName));
                    command.Parameters.Add(new OleDbParameter("@ExecutionID", _executionid));
                    command.Parameters.Add(new OleDbParameter("@handlerdatetime", _handlerdatetime));
                    command.Parameters.Add(new OleDbParameter("@uid", _uid));
                }

                command.CommandText = commandText;
                command.CommandType = CommandType.Text;
                command.Connection = _connection;

                command.ExecuteNonQuery();
                _connection.Close();
                return DTSExecResult.Success;

            }
            catch (Exception exc)
            {
                componentEvents.FireError(0, "CustomLoggingTask-Execute", "Task Errored: " + exc.ToString(), "", -1);
                return DTSExecResult.Failure;
            }
        }

        private void ReadVariables(VariableDispenser variableDispenser)
        {
            variableDispenser.LockForRead("System::StartTime");
            variableDispenser.LockForRead("System::PackageName");
            variableDispenser.LockForRead("System::SourceName");
            variableDispenser.LockForRead("System::MachineName");
            variableDispenser.LockForRead("System::ExecutionInstanceGUID");
            variableDispenser.LockForRead("System::EventHandlerStartTime");
            variableDispenser.LockForRead("User::UID");
            bool includesError = variableDispenser.Contains("System::ErrorCode");
            if (includesError)
            {
                variableDispenser.LockForRead("System::ErrorCode");
                variableDispenser.LockForRead("System::ErrorDescription");
            }

            Variables vars = null;
            variableDispenser.GetVariables(ref vars);

            DateTime startTime = (DateTime)vars["System::StartTime"].Value;
            _packageDuration = DateTime.Now.Subtract(startTime).TotalSeconds;
            _packageName = vars["System::PackageName"].Value.ToString();
            _taskName = vars["System::SourceName"].Value.ToString();
            _machineName = vars["System::MachineName"].Value.ToString();
            _executionid = vars["System::ExecutionInstanceGUID"].Value.ToString();
            _handlerdatetime = (DateTime)vars["System::EventHandlerStartTime"].Value;
            _uid = vars["User::UID"].Value.ToString();
            if (includesError)
            {
                _errorCode = vars["System::ErrorCode"].Value.ToString();
                _errorDescription = vars["System::ErrorDescription"].Value.ToString();
            }

            // release the variable locks.
            vars.Unlock();

            // reset the dispenser
            variableDispenser.Reset();
        }
    }
}

只是为了记录,我给您留下了一些我发现对开发、部署和调试自定义组件有用的链接(但也许您已经浏览过它们!):

http://bennyaustin.wordpress.com/2009/06/30/steps-to-build-and-deploy-custom-ssis-components/ http://bennyaustin.wordpress.com/2009/06/30/steps-to-build-and-deploy-custom-ssis-components/

http://msdn.microsoft.com/en-us/library/ms403356%28v=sql.105%29.aspx http://msdn.microsoft.com/en-us/library/ms403356%28v=sql.105%29.aspx

http://toddmcdermid.blogspot.com.ar/2009/06/converting-your-script-task-into-custom_22.html http://toddmcdermid.blogspot.com.ar/2009/06/converting-your-script-task-into-custom_22.html

Cheers.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

缺少引用 OLEDB 连接类型的库 的相关文章

随机推荐

  • 如何使用链接表在 Hibernate 中映射多对多列表

    我想使用链接表在 Hibernate 中映射多对多 我有两个课程 父级和子级 例如 public class Parent private List
  • HashMap 反向排序? [复制]

    这个问题在这里已经有答案了 所以我遇到了这个方法 它能够按值对 HashMap 进行排序 public static
  • 如何将 Selenium 连接到现有的 Firefox 浏览器? (Python)

    有谁知道如何将现有的 Firefox 浏览器与 Selenium 连接 我尝试了 Chrome 方式 没有运气 在调试模式下启动 Firefox start firefox exe marionette foreground no remo
  • 在 R 中追加数据

    我正在生成一个脚本 在其中对一堆数据进行了许多操作 并且对另一个数据集进行了相同的操作 两个数据集具有相同的行 列和标题 我希望能够将两个数据集连接在一起 将数据集 A 放置在数据集 B 之上 我不需要数据集 B 的标题 而是将所有数据聚集
  • 如何使表格中的整行可作为链接点击?

    我正在使用 Bootstrap 但以下内容不起作用 tbody a href tr td Blah Blah td td 1234567 td td 158 000 td tr a tbody 作者注一 请查看下面的其他答案 尤其是那些不使
  • Python 中的按位运算是如何进行的?

    我今天一直在学习按位运算 我了解到Not 反转所有位 例如 01010 to 10101 这意味着 10应该是 5 但我看到它是 11 每个python命令行 这是 01010 to 11011 只有两位被反转 谁能解释一下为什么不是101
  • UVa 的 3n+1 挑战

    我在运行 编程挑战 中的 3n 1 问题 时遇到问题 我已经尝试了在 google 上找到的所有 Java 解决方案 甚至是 Stack Overflow 上的解决方案 但没有一个有效 它们都报告 错误答案 我还找到了一个可行的 C 解决方
  • Android EditText 输入类型 textShortMessage

    inputType 的目的是什么textShortMessage https developer android com reference android text InputType html TYPE TEXT VARIATION S
  • 如何在列表中的任意位置插入元素?

    我有这个 gt gt gt a 1 4 7 11 17 有什么办法可以增加4个字符吗 随机地在其他元素之间实现 例如 1 4 7 11 17 你可以简单地这样做 import random for in range 4 a insert r
  • NSMutableArray 属性初始化和更新

    假设我有一个 property 它是一个 NSMutablearray 其中包含四个对象使用的分数 它们将被初始化为零 然后在 viewDidLoad 期间和应用程序的整个操作过程中更新 由于某种原因 我无法全神贯注于需要做什么 特别是在声
  • 删除其他工作表上的列中*不*存在值的行

    我有一个包含两张纸的 LibreOffice Calc 文件 表 2 只有一列 A 其中有很多数字 在工作表 1 中 每行的 A 列也包含一个数字 我想从工作表 1 中删除 A 列中具有值的所有行not appear anywhere在表
  • 在 json 模式中定义键值对的正确方法是什么

    如何在 json 模式中定义键值对对象 正确 方式 我想定义这个 id 99 info name somename href someUrl 以下两项是否准确 1 type object name MyObj properties id t
  • 运算符 ++ 中的 Int 参数

    class myClass public void operator myInstance void operator int myInstance 除了让编译器区分myInstance and myInstance 是可选的int论证中o
  • App Engine (Python) 数据存储区预调用 API 挂钩

    背景 假设我正在为 GAE 制作应用程序 并且我想使用API 钩子 http code google com appengine articles hooks html BIG EDIT 在这个问题的原始版本中 我描述了我的用例 但有些人正
  • 为什么有时 jQuery 选择器会返回类似“a.fn.init”的内容? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我不知道我的 Chrome 浏览器发生了什么 但突然出现了这样的行为 div my 控制台中的内容与以前完全不同 我曾经经历过一次 但后来又
  • NSOpenPanel 无法获得焦点

    首先 我对 Swift 完全陌生 如果我的问题看起来微不足道 我很抱歉 我想要一个非常简单的命令行程序 它打开一个对话框来选择文件或文件夹 该工具不得运行带有在 Dock 中弹跳的图标的实际完整应用程序 而是运行一些微妙的东西 就是这样 我
  • 使用 Direct2D/DirectWrite 确定文本边界框

    ID2D1RenderTarget DrawGlyphRun采用以下参数 D2D1 POINT 2F baselineOrigin in CONST DWRITE GLYPH RUN glyphRun in ID2D1Brush foreg
  • 如何将 pandas 中的字符串转换为日期时间格式?

    我有一个专栏I DATE数据框中的字符串 对象 类型称为train如下图所示 I DATE 28 03 2012 2 15 00 PM 28 03 2012 2 17 28 PM 28 03 2012 2 50 50 PM 如何转换I DA
  • 条件面板 R 中的多个条件闪亮

    在闪亮的应用程序中使用条件面板时是否可以有多个条件 我想隐藏几个选项卡的特定 UI 组件 以下是我正在尝试的内容 但当我有多个条件时它似乎并不适用 library shiny library shinyWidgets library shi
  • 缺少引用 OLEDB 连接类型的库

    我从以下代码中得到了SSIS 团队博客 http blogs msdn com b mattm archive 2008 08 22 accessing oledb connection managers in a script aspx转