通过 DLL 进行 Sybase 批量复制:值不在预期范围内
Sybase Bulk Copy via DLL: Value does not fall within the expected range
我正在尝试使用随 Sybase 安装提供的 .net DLL(Sybase.AdoNet4.AseClient.dll 版本 16.0.02)将数据从 Sql 服务器迁移到 Sybase 16.0 数据库。
为了简单起见,我试图从具有单个 INT 列的 table 中复制值
--source table (MSSQL)
CREATE TABLE [dbo].[TO_INTS](
[TO_INT] [int] NULL,
[TO_INT2] [int] NULL,
[NAME] [varchar](50) NULL,
[DT] [datetime] NULL
) ON [PRIMARY]
到
--target table (Sybase)
CREATE TABLE dbo.TO_INTS
(
FROM_INT INT NOT NULL
)
ON 'default'
我正在使用代码:
public void BulkCopyFromSqlServer(string sourceConnectionString, string targetConnectionString)
{
SqlConnection sourceConnection = null;
AseConnection targetConnection = new AseConnection(targetConnectionString);
IDataReader dataSource=null;
try
{
targetConnection.Open();
MssqlCommand.GetDataReader(sourceConnectionString, out sourceConnection, out dataSource); //see below
AseBulkCopy blk = new AseBulkCopy(targetConnection);
blk.BulkCopyTimeout = 1200;
blk.DestinationTableName = "TO_INTS";
blk.ColumnMappings.Clear();
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(0,0));
blk.WriteToServer(dataSource); // System.ArgumentException thrown here.
blk.Close();
}
catch (AseException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
sourceConnection.Dispose();
targetConnection.Dispose();
}
}
//MssqlCommand.GetDataReader(sourceConnectionString, out sourceConnection, out dataSource):
public static void GetDataReader(string sqlServerConnectionString, out SqlConnection conn, out IDataReader reader)
{
conn = new SqlConnection(sqlServerConnectionString);
conn.Open();
SqlCommand cmd = new SqlCommand("select * from TO_INTS", conn);
cmd.CommandTimeout = 60;
reader = cmd.ExecuteReader();
}
当使用消息“Value does not fall within the expected range
”调用 WriteToServer()
时抛出 System.ArgumentException。
堆栈跟踪很有趣,因为它看起来像 Sybase DLL 无法使用映射中提供的索引解析数据库列名,这看起来很奇怪:
at Sybase.Data.AseClient.AseBulkCopy.GetDBColName(String clientColName, Int32 clientColInx)
at Sybase.Data.AseClient.AseBulkCopy.GenerateInsertCmdByReaderMetaInfo(DataTable rowFmt)
at Sybase.Data.AseClient.AseBulkCopy.WriteToServer(IDataReader reader)
我对 Sybase > Sql 服务器执行了相同的过程(几乎一行一行,但切换了相关的 DLL)并且这有效。
我是不是遗漏了什么明显的东西?
除此之外,我没有任何即时观察结果:MS SQL 中的源 table 与 ASE 中的目标 table 在两个方面不同:
它的列较少并且
ASE 中的列名与 MS 中的列名不同SQL。
如果不了解这里发生的事情的全部范围和上下文,不难想象源和目标之间会发生不匹配 table。
看来我现在已经解决了这个问题。
我的代码有两个错误。
最初的错误是因为我不知道将 EnableBulkLoad
参数放在连接字符串中。我的工作连接字符串如下所示:
string SybaseConnectionString = "Data Source=server1;Initial Catalog=mydb;persist security info=False;User Id=sa;Password=password1;Port=5000;EnableBulkLoad=2"
添加后出现第二个错误:
Bad row data received from the client while bulk copying into object 2080007410 partition 2080007410 in database 6. Received a row of length 11 whilst maximum or expected row length is 6.
出现这种情况是因为 table 名称是使用以下方法设置的:
blk.DestinationTableName = "TO_INTS";
应该是什么时候:
blk.DestinationTableName = "dbo.TO_INTS";
一旦我添加了所有者,BulkCopy 就起作用了。
作为参考,现在我已经开始工作了,我可以在 table 之间完成具有不同名称的 WriteToServer 调用。此外,列名在每个 table 中是唯一的,即 source Sql Server table:
CREATE TABLE [dbo].[SOURCE_INTS](
[TO_INT] [int] NULL,
[TO_INT2] [int] NULL,
[NAME] [varchar](50) NULL,
[DT] [datetime] NULL
) ON [PRIMARY]
目标 Sybase table:
CREATE TABLE dbo.TO_INTS
(
THE_STRING VARCHAR(50) NOT NULL,
THE_INT INT NOT NULL,
THE_DT DATETIME NOT NULL
)
LOCK ALLPAGES
ON 'default'
GO
您还会注意到顺序不同,但 WriteToServer
使用映射可以很好地处理此问题:
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(2, 0)); //string col
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(1, 1)); //int col
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(3, 2)); //datetime col
如果您需要有关 C# 的 Sybase 数据提供程序的更多信息,请尝试 Sybase Books Online
希望这对某人有所帮助。
我正在尝试使用随 Sybase 安装提供的 .net DLL(Sybase.AdoNet4.AseClient.dll 版本 16.0.02)将数据从 Sql 服务器迁移到 Sybase 16.0 数据库。
为了简单起见,我试图从具有单个 INT 列的 table 中复制值
--source table (MSSQL)
CREATE TABLE [dbo].[TO_INTS](
[TO_INT] [int] NULL,
[TO_INT2] [int] NULL,
[NAME] [varchar](50) NULL,
[DT] [datetime] NULL
) ON [PRIMARY]
到
--target table (Sybase)
CREATE TABLE dbo.TO_INTS
(
FROM_INT INT NOT NULL
)
ON 'default'
我正在使用代码:
public void BulkCopyFromSqlServer(string sourceConnectionString, string targetConnectionString)
{
SqlConnection sourceConnection = null;
AseConnection targetConnection = new AseConnection(targetConnectionString);
IDataReader dataSource=null;
try
{
targetConnection.Open();
MssqlCommand.GetDataReader(sourceConnectionString, out sourceConnection, out dataSource); //see below
AseBulkCopy blk = new AseBulkCopy(targetConnection);
blk.BulkCopyTimeout = 1200;
blk.DestinationTableName = "TO_INTS";
blk.ColumnMappings.Clear();
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(0,0));
blk.WriteToServer(dataSource); // System.ArgumentException thrown here.
blk.Close();
}
catch (AseException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
sourceConnection.Dispose();
targetConnection.Dispose();
}
}
//MssqlCommand.GetDataReader(sourceConnectionString, out sourceConnection, out dataSource):
public static void GetDataReader(string sqlServerConnectionString, out SqlConnection conn, out IDataReader reader)
{
conn = new SqlConnection(sqlServerConnectionString);
conn.Open();
SqlCommand cmd = new SqlCommand("select * from TO_INTS", conn);
cmd.CommandTimeout = 60;
reader = cmd.ExecuteReader();
}
当使用消息“Value does not fall within the expected range
”调用 WriteToServer()
时抛出 System.ArgumentException。
堆栈跟踪很有趣,因为它看起来像 Sybase DLL 无法使用映射中提供的索引解析数据库列名,这看起来很奇怪:
at Sybase.Data.AseClient.AseBulkCopy.GetDBColName(String clientColName, Int32 clientColInx)
at Sybase.Data.AseClient.AseBulkCopy.GenerateInsertCmdByReaderMetaInfo(DataTable rowFmt)
at Sybase.Data.AseClient.AseBulkCopy.WriteToServer(IDataReader reader)
我对 Sybase > Sql 服务器执行了相同的过程(几乎一行一行,但切换了相关的 DLL)并且这有效。
我是不是遗漏了什么明显的东西?
除此之外,我没有任何即时观察结果:MS SQL 中的源 table 与 ASE 中的目标 table 在两个方面不同:
它的列较少并且
ASE 中的列名与 MS 中的列名不同SQL。
如果不了解这里发生的事情的全部范围和上下文,不难想象源和目标之间会发生不匹配 table。
看来我现在已经解决了这个问题。
我的代码有两个错误。
最初的错误是因为我不知道将 EnableBulkLoad
参数放在连接字符串中。我的工作连接字符串如下所示:
string SybaseConnectionString = "Data Source=server1;Initial Catalog=mydb;persist security info=False;User Id=sa;Password=password1;Port=5000;EnableBulkLoad=2"
添加后出现第二个错误:
Bad row data received from the client while bulk copying into object 2080007410 partition 2080007410 in database 6. Received a row of length 11 whilst maximum or expected row length is 6.
出现这种情况是因为 table 名称是使用以下方法设置的:
blk.DestinationTableName = "TO_INTS";
应该是什么时候:
blk.DestinationTableName = "dbo.TO_INTS";
一旦我添加了所有者,BulkCopy 就起作用了。
作为参考,现在我已经开始工作了,我可以在 table 之间完成具有不同名称的 WriteToServer 调用。此外,列名在每个 table 中是唯一的,即 source Sql Server table:
CREATE TABLE [dbo].[SOURCE_INTS](
[TO_INT] [int] NULL,
[TO_INT2] [int] NULL,
[NAME] [varchar](50) NULL,
[DT] [datetime] NULL
) ON [PRIMARY]
目标 Sybase table:
CREATE TABLE dbo.TO_INTS
(
THE_STRING VARCHAR(50) NOT NULL,
THE_INT INT NOT NULL,
THE_DT DATETIME NOT NULL
)
LOCK ALLPAGES
ON 'default'
GO
您还会注意到顺序不同,但 WriteToServer
使用映射可以很好地处理此问题:
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(2, 0)); //string col
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(1, 1)); //int col
blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(3, 2)); //datetime col
如果您需要有关 C# 的 Sybase 数据提供程序的更多信息,请尝试 Sybase Books Online
希望这对某人有所帮助。