2015-01-12 1 views
0

Я пытаюсь перенести данные с Sql Server в базу данных Sybase 16.0 с использованием .net DLL, поставляемых с установкой Sybase (версия Sybase.AdoNet4.AseClient.dll 16.0.02).Sybase Bulk Copy через DLL: значение не попадает в ожидаемый диапазон

Для простоты я пытаюсь скопировать значения из таблицы с одного столбца INT

--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(); 
} 

Исключение System.ArgumentException запускается при вызове WriteToServer() с сообщением «Value does not fall within the expected range ". Трассировка стека интересен тем, что он выглядит как Sybase DLL не может разрешить columnn имя БД с помощью индекса, представленную в отображении, что кажется странным:

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 Server (довольно много строк за строкой, но с соответствующими DLL-переключателями), и это работает.

Я пропустил что-то очевидное?

ответ

0

Похоже, я исправил это сейчас.

В моем коде было две ошибки.

Исходная ошибка возникла из-за того, что я не знал о пометке параметра 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. 

Этот вопрос возник потому, что имя таблицы было установлено с помощью:

blk.DestinationTableName = "TO_INTS"; 

когда оно должно быть:

blk.DestinationTableName = "dbo.TO_INTS"; 

Как только я добавил владельца, то BulkCopy работал.

Для ссылки, теперь, когда у меня есть работа, я могу завершить вызов WriteToServer между таблицами с разными именами.Кроме того, имена столбцов являются уникальными в каждой таблице, то есть источник Sql Server таблица:

CREATE TABLE [dbo].[SOURCE_INTS](
    [TO_INT] [int] NULL, 
    [TO_INT2] [int] NULL, 
    [NAME] [varchar](50) NULL, 
    [DT] [datetime] NULL 
) ON [PRIMARY] 

Цель Sybase таблица:

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 

Если Вам необходима дополнительная информация о поставщике Sybase данных для C#, попробуйте Sybase Books Online

Надеюсь, это поможет кому-то.

0

У меня нет каких-либо других, чем непосредственные наблюдения этого один: ваш источник таблицы в MS SQL отличается от целевой таблицы в ASE двумя способами:

  1. имеет меньше столбцов и

  2. имя столбца в ASE отличается от имен столбцов в MS SQL.

Не понимая полного объема и контекста того, что здесь происходит, было бы нелегко представить несоответствие между исходной и целевой таблицей.

+0

Я думал, что был покрыт ColumnMappings. Должны ли исходные и целевые таблицы иметь одинаковые имена и одинаковые имена столбцов, типы и порядок? – Badgerspot

+0

Получается, что исходные и целевые таблицы не должны иметь одинаковые имена и точно одинаковые имена и порядок столбцов. – Badgerspot

Смежные вопросы