2015-06-12 68 views
0

我有一個U2/UniVerse數據庫,並且需要將一個表中的數據複製到SQL Server表中。有問題的表格大約有600,000行,只有200列。我沒有創建表格,也無法更改它。將UniDataSet複製到SQL Server的最有效方法是什麼?

對於其他表,我一次循環一個記錄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。然後,我SqlBulkCopyDataTable到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); 
    } 
} 

這只是正常的有5萬行左右我的U2表,但它基本上崩潰調試器(VS快遞2012)當表中有50萬行數據。我正在使用的PC是帶有4GB RAM的Windows 7 x64。 VS進程看起來像在崩潰之前使用高達3.5GB的RAM。

我希望有一種方法可以使用SqlBulkCopy編寫SQL的UniDataSet權限,但我對U2 .Net工具箱不太熟悉。

我面對的問題是UniDataSet記錄是多值的,我需要在將它們寫入SQL之前將它們分開。

謝謝!

回答

1

DataTable在插入到數據庫之前在內存中變得更大。 爲什麼不拆分批量插入操作?例如,讀取第一個50.000結果並將其插入到Sql服務器數據庫中,清除DataTable內存並再次使用下一個50.000行開始。

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

我想類似的東西,現在,在那裏我刪除從UniFile記錄的一半,運行我的代碼的其餘部分,然後與另一半做一遍。謝謝你的建議..我也會嘗試這種方式。 –

+0

我接受了這個,因爲它是我解決方案的基礎(也是我得到的唯一答案.. :)。我將'SqlBulkCopy'移到了'ForEach'循環中,並以'if(dt.Rows.Count == 300000 || uSet.AfterLast == true)'作爲前綴。這會引發SqlBulkCopy兩次,一次大約通過'UniDataSet'的一半,然後再次結束。謝謝! –

1

在U2 Toolkit for .NET v2.1.0中,我們實現了Native Access。現在您可以直接從UniData/UniVerse文件創建DataSet/DataTable。你也可以指定WHERE和SORT子句。你會看到性能的改善,因爲它不會讓太多的服務器旅程獲取ID。例如,如果您有1000個記錄ID,則它將使服務器跳閘達到1000次。而如果您使用本地訪問,它將使一個服務器旅程。

請下載U2 Toolkit for .NET v2.2.0 Hot Fix 1並嘗試下面的代碼。欲瞭解更多信息,請聯繫[email protected]

  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]; 
+0

Rajan,這太棒了!我會試一試。我將如何修改您的Select語句以將所有屬性包含在給定的U2表中? –

+0

這不建議。但是如果你的字典是乾淨的,你可以嘗試下面的語法。 cmd.CommandText = string.Format(「Action = Select; File = MyU2TableName」); 我們正在尋找「@ID」以外的字典中的ID。例如,序號/位置0可以有@ID和MYID。 請在此處查看更多示例代碼:C:\ Program Files(x86)\ Rocket Software \ U2 Toolkit for .NET \ U2數據庫提供程序\ samples \ C#\ UniData \ NativeAccess。 Regards, Rajan –

+0

當碰到'da.Fill(ds)'時,出現錯誤「Object reference not set to a instance of a object」。查看示例代碼時,我看到連接字符串使用'RpcServiceType = udcs',但我的代碼使用uvcs。使用udcs時,我無法連接到服務器。 –

相關問題