Какой самый эффективный способ скопировать UniDataSet в SQL Server?

У меня есть база данных U2/UniVerse, и мне нужно скопировать данные из одной таблицы в таблицу SQL Server. В рассматриваемой таблице около 600 000 строк и чуть менее 200 столбцов. Я не создал таблицу и не могу ее изменить.

Для других таблиц я перебираю UniDataSet по одной записи за раз и добавив ее в DataTable, а затем с помощью SqlBulkCopy скопировать записи на SQL Server. Это работает нормально, но с большой таблицей у меня, кажется, не хватает памяти при создании DataTable,

DataTable dt = new DataTable("myTempTable");
dt.Columns.Add("FirstColumn", typeof(string));
dt.Columns.Add("SecondColumn", typeof(string));
... //adding a bunch more columns here
dt.Columns.Add("LastColumn", typeof(string));

U2Connection con = GetU2Con();
UniSession us1 = con.UniSession;
UniSelectList s1 = us1.CreateUniSelectList(0);
UniFile f1 = us1.CreateUniFile("MyU2TableName")
s1.Select(f1);

UniDataSet uSet = f1.ReadRecords(s1.ReadListAsStringArray());

foreach (UniRecord uItem in uSet)
{
    List<String> record = new List<String>(uItem.Record.ToString().Split(new string[] { "þ" }, StringSplitOptions.None));

    DataRow row = dt.NewRow();

    row[0] = uItem.RecordID;
    row[1] = record[0];
    row[2] = record[1];
    ... //add the rest of the record
    row[50] = record[49]

    dt.Rows.Add(row);
}

con.Close();

Так что копирует записи из UniDataSet в DataTable, Затем я SqlBulkCopy DataTable в таблицу SQL:

string SQLcon = GetSQLCon();

using (SqlBulkCopy sbc = new SqlBulkCopy(SQLcon))
{
    sbc.DestinationTableName = "dbo.MySQLTableName";
    sbc.BulkCopyTimeout = 0;
    sbc.BatchSize = 1000; //I've tried anywhere from 50 to 50000

    try
    {
        sbc.WriteToServer(dt);
    }
    catch
    {
        Console.WriteLine(ex.Message);
    }
}

Это прекрасно работает для моих таблиц U2, которые содержат около 50000 строк, но в основном это приводит к сбою отладчика (VS Express 2012), когда в таблице 500 000 строк. ПК, на котором я это делаю - это Windows 7 x64 с 4 ГБ оперативной памяти. Процесс VS выглядит так, будто до сбоя использует до 3,5 ГБ ОЗУ.

Я надеюсь, что есть способ написать UniDataSet прямо на SQL с помощью SqlBulkCopy, но я не слишком знаком с инструментарием U2 .Net.

Проблема, с которой я сталкиваюсь, состоит в том, что записи UniDataSet являются многозначными, и мне нужно выделить их, прежде чем я смогу записать их в SQL.

Спасибо!

2 ответа

Решение

DataTable становится слишком много в памяти, прежде чем вставить в базу данных. Почему бы вам не разделить операцию массовой вставки? Например, прочитайте первые 50 000 результатов и вставьте их в базу данных сервера Sql, очистите память DataTable и начните снова со следующих 50 000 строк.

if (dt.Rows.Count > 50000)
{
    //do SqlbulkCopy
    dt.Rows.Clear();
}

В U2 Toolkit для.NET v2.1.0 мы реализовали Native Access. Теперь вы можете напрямую создавать DataSet/DataTable из файла UniData/UniVerse. Вы также можете указать WHERE и SORT. Вы увидите улучшение производительности, так как не будет слишком много Серверной поездки, чтобы получить идентификаторы. Например, если у вас есть 1000 идентификаторов записей, это приведет к 1000-кратному отключению сервера. Принимая во внимание, что если вы используете Native Access, он совершит одно отключение сервера.

Пожалуйста, скачайте U2 Toolkit для.NET v2.2.0 Hot Fix 1 и попробуйте следующий код. Для получения дополнительной информации, пожалуйста, свяжитесь с u2askus@rocketsoftware.com.

            U2Connection con = GetU2Con();
            U2Command cmd = lConn.CreateCommand();
            cmd.CommandText = string.Format("Action=Select;File=MyU2TableName;Attributes=MyID,FirstColumn,SecondColumn,LastColumn;Where=MyID>0;Sort=MyID");
            U2DataAdapter da = new U2DataAdapter(cmd);
            DataSet ds = new DataSet();
            da.Fill(ds);
            DataTable dt = ds.Tables[0]; 
Другие вопросы по тегам