4

N 個のデータテーブルがあり、N-1 個のデータテーブルがいくつかのエンティティを表し、1 個がこれらのエンティティ間の関係を表しています。

Entity Countryのように

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

ただし、このメソッドはすべてのデータテーブルを反復し、リレーションシップデータに変換するエンティティがさらにある場合は非常に遅くなります。したがって、このコードを最適化して、多数の行を持つ多数のデータテーブルを操作するにはどうすればよいですか。

編集済み : ほとんどの場合、これらのデータは DB に保存されません。これらはメモリ内にあり、メモリ内ではこれらのデータテーブルの数を増減できます。

ありがとう。

4

3 に答える 3

3

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 ...
于 2012-08-17T07:40:29.070 に答える
2

問題自体は本当に単純なように思えます。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}; 
于 2012-08-17T07:50:13.527 に答える
2

ここでの解決策は、ID 列がキーであり、.Select(Id = x) の代わりにそれを使用して、ハッシュ ベースのコレクション (つまり、.NET の hashtables、dictionary、lookups) を作成することです。

コードは次のようになります....テストされていません。

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; 
    } 
于 2012-08-23T16:31:57.333 に答える