2012-07-25 50 views
4

我有N個數據表,其中N-1個數據表表示一些實體,1表示這些實體之間的關係。一個DataTable,它具有來自其他數據表的id,需要轉換這個數據表來替換id與他們的數據表名列值

實體國家

Country DATATABLE 

ID | Country Name | Country Code 
------------------------------------ 
ID1 | USA   | USA 
ID2 | INDIA  | IND 
ID3 | CHINA  | CHI 

實體大陸

Continent DATATABLE 

ID  | Continent Name | Continent Code 
------------------------------------ 
IDC1 | NORTH AMERICA | NA 
IDC2 | SOUTH AMERICA | SA 
IDC3 | ASIA   | AS 

實體公司

Company DATATABLE 

ID | Company Name | Company Code 
------------------------------------ 
CM1 | XYZ Company | XYZ 
CM2 | Fun Company | Fun 
CM3 | ABC Company | ABC 

這些之間的關係。

Company_Country_Continent_Relationship DataTable 

ID | Company  | Country | Continent  | Some Value1  | Some Value 2 
------------------------------------------------------------------------------------- 
R1 | CM1   | ID1  | IDC1   | 100    | 150 
R2 | CM2   | ID2  | IDC3   | 200    | 200 
R3 | CM3   | ID1  | IDC1   | 150    | 250 
R4 | CM1   | ID3  | IDC3   | 100    | 150 
R5 | CM2   | ID1  | IDC1   | 200    | 200 
R6 | CM3   | ID2  | IDC3   | 150    | 250 
R7 | CM1   | ID2  | IDC3   | 100    | 150 
R8 | CM2   | ID3  | IDC3   | 200    | 200 
R9 | CM3   | ID3  | IDC3   | 150    | 250 

現在我需要生成另一個關係表,將舉行,而不是ID名稱。 在這個例子中,關係數據存儲公司,國家和大陸的ID,現在我想將這些id值轉換成那裏的名字,而不是CM1 - XYZ公司。

對於此轉換,我正在使用方法TramnsformRelationshipData,它正在正常工作。

public static DataTable TramnsformRelationshipData(DataTable relationshipData, Dictionary<string, DataTable> mapping) 
    { 
     DataTable transformedDataTable = null; 
     if (relationshipData == null || mapping == null) 
      return null; 

     transformedDataTable = relationshipData.Copy(); 

     foreach (DataColumn item in relationshipData.Columns) 
     { 
      if (mapping.ContainsKey(item.ColumnName)) 
      { 
       var instanceData = mapping[item.ColumnName]; 
       if (instanceData == null) 
        return null; 

       foreach (DataRow row in transformedDataTable.Rows) 
       { 
        var filteredRows = instanceData.Select("ID = '" + row[item.ColumnName] + "'"); 
        if (filteredRows.Any()) 
         row[item.ColumnName] = filteredRows[0][1]; 
       } 
      } 
     } 

     return transformedDataTable; 
    } 

但是,這種方法迭代所有的數據表,並且是非常緩慢的,當有更多的實體relationshipdata改造。那麼,我怎樣才能優化這段代碼,以處理大量數據表中的大量行。

編輯:在大多數情況下,這些數據不會存儲在數據庫中,它們存儲在內存中,並且在內存中這些數據表的計數可以增加或減少。

謝謝。

+0

如果存儲在內存中,它是否需要DataTable?將它加載到像dictionries這樣的結構中會不會更有效? 如果您最初從數據庫加載它,則可以使用簡單快速的數據閱讀器來填充字典。 – ElDog 2012-08-23 14:11:45

回答

2

這裏的解決方案是創建一個基於散列的集合(即哈希表,字典,在查找。 NET) 與ID列是關鍵和使用,而不是.Select(Id = x)

代碼可能看起來像這樣....未經測試。

public static DataTable TramnsformRelationshipData(DataTable relationshipData, Dictionary<string, DataTable> mapping) 
    { 
     Dictionary<string,Dictionary<string,DataRow>> newMappings = new Dictionary<string,Dictionary<string,DataRow>>(); 
     foreach (var kvp in mapping) 
     { 
      newMappings.Add(kvp.Key,kvp.Value.Rows.Cast<DataRow>().ToDictionary(dr=>dr["ID"] as string)); 
     } 

     DataTable transformedDataTable = null; 
     if (relationshipData == null || mapping == null) 
      return null; 

     transformedDataTable = relationshipData.Copy(); 

     foreach (DataColumn item in relationshipData.Columns) 
     { 
      if (newMapping.ContainsKey(item.ColumnName)) 
      { 
       var instanceData = newMapping[item.ColumnName]; 
       if (instanceData == null) 
        return null; 

       foreach (DataRow row in transformedDataTable.Rows) 
       { 
       // var filteredRows = instanceData.Select("ID = '" + row[item.ColumnName] + "'"); 
       // if (filteredRows.Any()) 
        row[item.ColumnName] = instanceData[row[item.ColumnName]][1];      
       } 
      } 
     } 

     return transformedDataTable; 
    } 
3

您是否考慮用SELECT INTO語句創建SQL代碼(這將比使用C#代碼快得多)?當我需要處理大量數據時,我通常更喜歡使用SQL。

示例取自this MSDN頁面。

SELECT c.FirstName, c.LastName, e.JobTitle, a.AddressLine1, a.City, sp.Name AS [State/Province], a.PostalCode 
INTO dbo.EmployeeAddresses 
FROM Person.Person AS c JOIN HumanResources.Employee AS e ON e.BusinessEntityID = c.BusinessEntityID 
JOIN Person.BusinessEntityAddress AS bea ON e.BusinessEntityID = bea.BusinessEntityID 
JOIN Person.Address AS a ON bea.AddressID = a.AddressID 
JOIN Person.StateProvince as sp ON sp.StateProvinceID = a.StateProvinceID; 

先寫一個SELECT語句獲取數據,然後添加INTO聲明。

或者您可以使用INSERTSELECT您可以在其中指定要插入數據的列的列表。取自MSDN頁面的示例。

INSERT INTO Production.ZeroInventory (DeletedProductID, RemovedOnDate) 
SELECT ProductID, GETDATE() FROM ... 
+0

但是,在大多數情況下,這些數據不會存儲在數據庫中,它們存儲在內存中,並且在內存中這些數據表的計數可以增加或減少。 – 2012-08-17 07:48:51

+0

你忘了在你的問題中提到這個。 – 2012-08-17 07:49:54

2

在我看來,這個問題本身非常簡單,3個連接可以解決它,如果你使用SQL。
我猜源不在sql中(如果是我會推薦在那裏創建一個視圖,以獲得最佳性能)。
如果你必須使用數據集,你可以使用linq來模擬連接。

檢查此Link關於如何使用LINQ與數據集。
你可以找到如何做一個加入Here

最終的結果會是這個樣子:

var q = from r in relations.AsEnumerable() 
     join c in countries.AsEnumerable() on r.Country equals c.Id 
     join con in continents.AsEnumerable() on r.Continent equals con.Id 
     select new { someval = r.someValue1, 
        someval2 = r.someValue2, 
        countryname = c.Name 
        continent = con.Name}; 
+0

我知道,如何使用LINQ與數據集。但數據表的數量是任意的,數據表可以有任意數量的行和列,並且有問題,我提到有N個數據表。 – 2012-08-17 07:59:17

+0

對不起,我錯過了那部分。您是否嘗試過使用以下語法在foreach中添加聯接:var joined = q.Join(countries.AsEnumerable(),a => a.Country,b => b.Id,(a,b)=> new {b .Somevalue,a.CC1}) – Kristof 2012-08-17 08:13:48

相關問題