Какой самый эффективный способ скопировать 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];