具有来自其他数据表的id的数据表,需要转换此数据表以将id替换为其数据表名称列值

  • 本文关键字:数据表 id 替换 其他 转换 c# datatable
  • 更新时间 :
  • 英文 :


我有N个数据表,其中N-1个数据表表示一些实体,1个表示这些实体之间的关系。

喜欢实体国家

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

现在我需要生成另一个关系表,它将包含Name而不是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;
    }

但是,当关系数据有更多的实体要转换时,这种方法会迭代所有的数据表,并且速度非常慢。那么,我该如何优化这段代码,以处理具有大量行的大量数据表。

编辑:在大多数情况下,这些数据不存储在数据库中,这些数据在内存中,在内存中这些数据表的计数可以增加或减少。

谢谢。

您是否考虑过使用SELECT INTO语句创建SQL代码(这将比使用C#代码快得多)?当我需要处理大量数据时,我通常更喜欢使用SQL。

示例取自此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 ...

这里的解决方案是创建一个基于哈希的集合(即哈希表、字典、.NET中的查找)ID列是键,并使用它而不是。选择(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; 
    } 

在我看来,问题本身非常简单,如果使用sql,3个联接可以解决它
我猜源代码不在sql中(如果是的话,我建议在那里创建一个视图以获得最大性能)
如果必须使用数据集,可以使用linq来模拟联接

请查看此链接,了解如何将linq与数据集一起使用
你可以在这里了解如何加入

最终结果看起来像这样:

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}; 

最新更新