我试图从SQLServer数据库中的CLR方法连接到DB2数据库。连接是通过OleDbConnection完成的。以前这种方法是有效的,但我们正在迁移到一个新的环境。我们过去使用IBM DB2 9.7驱动程序在SQL Server 2014上工作。现在,我们将使用最新的IBM DB2 11.5驱动程序在SQL Server 2019上工作。开发工作在中完成。NET Framework 4.8并使用CLR 4.0。由于更新了环境,我们现在在发布之前使用证书对CLR程序集进行签名。
CLR代码本身可以工作并且可以被调用,但是到DB2数据库的OleDbConnection不能工作。当运行OleDbConnection.Open()
方法时,我们得到以下错误:
A .NET Framework error occurred during execution of user-defined routine or aggregate "clrGetData":
System.Data.OleDb.OleDbException: Unspecified error
System.Data.OleDb.OleDbException:
at System.Data.OleDb.OleDbServicesWrapper.GetDataSource(OleDbConnectionString constr, DataSourceWrapper& datasrcWrapper)
at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)
at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.OleDb.OleDbConnection.Open()
奇怪的是,当我创建一个简单的控制台应用程序,试图通过OleDb连接到同一个数据库时,使用相同的连接字符串和相同的代码来初始化连接等,连接打开时没有问题,并且可以调用DB2数据库。(它调用SQL Server数据库上的CLR方法)和数据库服务器(CLR在其上运行并与DB2数据库建立连接)。
我还尝试通过将CLR代码复制到Web应用程序,直接从应用服务器上的Web应用程序连接到DB2数据库。这也没有任何问题。但是,由于我们当前的设置需要从数据库初始化两个数据库之间的同步,因此要完全替换CLR过程将需要大量的重构工作。
这是我们目前正在测试的CLR过程的一个示例:
[Microsoft.SqlServer.Server.SqlProcedure]
public static void clrGetData(string userId)
{
var connectionString = <Get connection string to DB2 database>;
using (var db2connection = new OleDbConnection(connectionString))
{
db2connection.Open();
if (db2connection == null) throw new ArgumentNullException("connection");
Microsoft.SqlServer.Server.SqlMetaData[] mdDos = new Microsoft.SqlServer.Server.SqlMetaData[1];
mdDos[0] = new Microsoft.SqlServer.Server.SqlMetaData("Profile", System.Data.SqlDbType.VarChar, 100);
string storedProcedure = string.Format("<Name of SP on DB2 database>");
var cmd = new DB2Command();
cmd.CommandText = storedProcedure;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Connection = db2connection;
// parameters
OleDbParameter dbParam;
dbParam = new OleDbParameter("<name>", OleDbType.Char, 10, "<srcColumn>");
dbParam.Value = userId;
dbParam.Direction = ParameterDirection.Input;
cmd.Parameters.Add(dbParam);
// Some other input parameters
// ...
dbParam = new OleDbParameter("<name>", DB2Type.Integer, 10, "<srcColumn>");
dbParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(dbParam);
// Some other output parameters
// ...
var reader = cmd.ExecuteReader();
Microsoft.SqlServer.Server.SqlPipe sqlpipe = Microsoft.SqlServer.Server.SqlContext.Pipe;
Microsoft.SqlServer.Server.SqlDataRecord record = new Microsoft.SqlServer.Server.SqlDataRecord(mdDos);
sqlpipe.SendResultsStart(record);
if (reader.Read())
{
record.SetValue(0, reader[5]);
sqlpipe.SendResultsRow(record);
}
sqlpipe.SendResultsEnd();
reader.Close();
db2connection.Close();
}
}
我已经扩展了控制台测试应用程序,使其也与OdbcConnection和DB2 Connection连接(通过引用IBM驱动程序中使用的IBM.Data.DB2.dll)。我使它们也都连接起来,但是当在CLR过程中使用它时,我又一次卡住了。
当使用Odbc时,我得到以下错误:
SqlException (0x80131904): A .NET Framework error occurred during execution of user-defined routine or aggregate "clrGetData":
System.Data.Odbc.OdbcException: ERROR [IM003] Specified driver could not be loaded due to system error 1114: A dynamic link library (DLL) initialization routine failed. (IBM DB2 ODBC DRIVER - DB2COPY1, D:\Program Files\IBM\SQLLIB\BIN\DB2CLIO.DLL).
System.Data.Odbc.OdbcException:
at System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)
at System.Data.Odbc.OdbcConnectionOpen..ctor(OdbcConnection outerConnection, OdbcConnectionString connectionOptions)
at System.Data.Odbc.OdbcConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.Odbc.OdbcConnection.Open()
在使用IBM dll时,我们遇到了一些问题,因为我们不能在不将外部引用作为程序集添加到SQL Server的情况下添加外部引用。由于IBM驱动程序本身可能引用了大量其他不受支持的引用,这将是一个需要解决的完全不同的问题。
下面是我们为每个方法使用的连接字符串:
// OleDb:
Provider=IBMDADB2.DB2COPY1;Database=<DB Name>;Hostname=<IP Address>;Protocol=TCPIP;Port=<Port Number>;Uid=<Username>;Pwd=<Password>;
// Odbc:
Driver={IBM DB2 ODBC DRIVER - DB2COPY1};Database=<DB Name>;Hostname=<IP Address>;Port=<Port Number>;Protocol=TCPIP;UID=<Username>;PWD=<Password>;
// IBM DB2:
Server=<IP Address>:<Port Number>;Database=<DB Name>;UID=<Username>;PWD=<Password>;
我试过在谷歌上搜索很多这样的问题,但是谷歌在这方面不是我的朋友,而且似乎还没有解决方案。
在SQL Server的CLR过程中连接到DB2数据库的最佳方法是什么?我们的设置/代码可能有什么问题?
编辑:
正如下面的评论者所问,db2level
命令的输出:
D:\Program Files\IBM\SQLLIB\BIN>db2level
DB21085I This instance or install (instance name, where applicable: "DB2")
uses "64" bits and DB2 code release "SQL11050" with level identifier
"0601010F".
Informational tokens are "DB2 v11.5.0.1077", "s1906101300",
"DYN1906101300WIN64", and Fix Pack "0".
Product is installed at "D:\Program Files\IBM\SQLLIB" with DB2 Copy Name
"DB2COPY1".
解决方案:
解决方案分为两部分:
- 11.5.0 IBM DB2客户端在加载DB2CLIO.dll文件时出现问题:(https://www.ibm.com/support/pages/apar/IT30451)。因此,已在数据库服务器上安装了最新的修复补丁程序。
- MSSQLSERVER用户被添加到DB2用户的Windows组中,以解决权限问题。
1条答案
按热度按时间kulphzqa1#
解决人:
经常检查IBM数据库产品和驱动程序的最新补丁包,这些都可以从补丁包中心网站下载。