Атрибут столбца «ORDINAL_POSITION» недопустим [Мастер импорта и экспорта — Visual FoxPro ProviderDescriptors.xml SSIS]

#sql #sql-server #ssis #odbc #visual-foxpro

#sql #sql-сервер #служба ssis #odbc #visual-foxpro

Вопрос:

Я пытаюсь синхронизировать базу данных Visual FoxPro с базой данных SQL Server.
Я использую мастер импорта и экспорта SQL Server (из SQL Server Data Tools).

Когда я нажимаю «Редактировать сопоставления …» Сначала у меня было 4 ошибки с той же проблемой, затем я изменил несколько значений в ProviderDescriptors.xml и в итоге получилось вот что:

 <dtm:ColumnSchemaAttributes
    NameColumnName = "COLUMN_NAME"
    OrdinalPositionColumnName="ORDINAL_POSITION"
    DataTypeColumnName = "TYPE_NAME"
    MaximumLengthColumnName = "LENGTH"
    NumericPrecisionColumnName = "PRECISION"
    NumericScaleColumnName = "SCALE"
    NullableColumnName="NULLABLE"
    NumberOfColumnRestrictions="4"
/>
  

Теперь единственная ошибка включена OrdinalPositionColumnName
Ошибка: The column attribute "ORDINAL_POSITION" is not valid

Для какого значения использовать OrdinalPositionColumnName (при использовании драйвера Visual FoxPro ODBC)?

Спасибо за помощь!

Комментарии:

1. Нет драйвера Foxpro ODBC (после версии 6.x). Вместо этого используйте драйвер VFPOLEDB.

2. @CetinBasoz Спасибо за ваш ответ! Я не мог использовать Microsoft OLE DB Provider for Visual FoxPro , потому что он выходит из строя, когда я выбираю это и нажимаю Properties...

3. Ну, я никогда не использовал его с SSIS. Я всегда сам пишу свои коды SQL server to-from на VFP или C #, Go, … Вы можете попробовать VFPOLEDB на связанных серверах. (Кстати, это 32-разрядный драйвер, при 64 битах он не будет работать).

4. Мой сервер MS SQl имеет 64 бита, так что, вероятно, это не сработает, как мне написать программу на C # для импорта базы данных таблиц без FVP на SQL Server?

5. Вы могли бы использовать класс SqlBulkCopy. Я могу дать вам пример кода в качестве ответа, если хотите.

Ответ №1:

Вот пример:

 void Main()
{
    string sqlConnectionString = @"server=.SQLExpress;Trusted_Connection=yes;Database=Test";
    // c:MyDataFoldermyTable.dbf
    string dataPath = @"c:MyDataFolder";
    string tableName = @"MyTable";

    Stopwatch sw = new Stopwatch(); // just for timing the sample run
    sw.Start();

    using (OleDbConnection cn = new OleDbConnection("Provider=VFPOLEDB;Data Source="   dataPath))
    using (SqlConnection scn = new SqlConnection(sqlConnectionString))
    {
        OleDbCommand cmd = new OleDbCommand($"select * from {tableName}", cn);
        SqlBulkCopy sbc = new SqlBulkCopy(scn, SqlBulkCopyOptions.TableLock, null);

        // Needed if VFP-SQL Server tables' field count or names are different
        // ie: LName in VFP might be LastName in SQL server
        // or VFP might have 10 fields when SQL server 8
        // VFP column names on left, SQL server column names on right
        sbc.ColumnMappings.Add("Category", "[Category]");
        sbc.ColumnMappings.Add("Activity", "[Activity]");
        sbc.ColumnMappings.Add("PersonId", "[PersonId]");
        sbc.ColumnMappings.Add("FirstName", "[FirstName]");
        sbc.ColumnMappings.Add("MidName", "[MidName]");
        sbc.ColumnMappings.Add("LastName", "[LastName]");
        sbc.ColumnMappings.Add("Email", "[Email]");

        cn.Open();
        scn.Open();

        // Since this is a sample, instead of wrting to a table
        // creating and writing to a global temporary table
        // You can see this table's data, connecting to the same database (global temp)
        SqlCommand createTemp = new SqlCommand();
        createTemp.CommandText = @"create table ##PersonData 
  (
    [Id] int identity primary key,
    [Category] varchar(50), 
    [Activity] varchar(50) default 'NullOlmasin', 
    [PersonId] varchar(50), 
    [FirstName] varchar(50), 
    [MidName] varchar(50), 
    [LastName] varchar(50), 
    [Email] varchar(50)
  )";
        createTemp.Connection = scn;
        createTemp.ExecuteNonQuery();

        OleDbDataReader rdr = cmd.ExecuteReader();

        sbc.NotifyAfter = 100000;
        sbc.BatchSize = 1000;
        sbc.BulkCopyTimeout = 10000;
        sbc.DestinationTableName = "##PersonData";

        sbc.SqlRowsCopied  = (sender, e) =>
          {
              Console.WriteLine("-- Copied {0} rows to {1}.[{2} milliseconds]",
          e.RowsCopied,
          ((SqlBulkCopy)sender).DestinationTableName,
          sw.ElapsedMilliseconds);
          };

        sbc.WriteToServer(rdr);

        if (!rdr.IsClosed) { rdr.Close(); }

        cn.Close();
        scn.Close();
    }
    sw.Stop();
    Console.WriteLine($"Done in {sw.ElapsedMilliseconds} milliseconds.");
}
  

Ответ №2:

Я знаю, что уже немного поздно, но я наткнулся на ваш вопрос, когда сам искал ответ, и я хотел задокументировать его здесь на случай, если в будущем кто-нибудь еще на моем месте будет искать эту проблему и найдет эту страницу.

Ответ — Radix

в контексте это выглядит так:

     <dtm:ColumnSchemaAttributes
        NameColumnName = "COLUMN_NAME"
        OrdinalPositionColumnName="Radix"
        DataTypeColumnName = "TYPE_NAME"
        MaximumLengthColumnName = "LENGTH"
        NumericPrecisionColumnName = "PRECISION"
        NumericScaleColumnName = "SCALE"
        NullableColumnName="NULLABLE"
        NumberOfColumnRestrictions="4"
    />