使用linq加入两个表,并填写它们的Dictionary

时间:2013-06-26 21:37:02

标签: c# sql-server performance linq linq-to-sql

我一直在搜索如何连接两个表(Data和DataValues,一对多)并填写类型字典。

数据的记录可能是数千(例如500,000或更多),每个数据可能有10到20个DataValues,这使得查询更加繁重,因此这里的性能非常重要。

这是我写的代码:

// Passed via the arguments, for example, sensorIDs would contain:
int[] sensorIDs = { 0, 1, 2, 3, 4, 5, 6, 17, 18 };
Dictionary<Data, List<DataValue>> dict = new Dictionary<Data, List<DataValue>>();

foreach (Data Data in dt.Datas)
{
    var dValues = from d in dt.Datas
                        join dV in dt.DataValues on d.DataID equals dV.DataID
                        where (SensorIDs.Contains(dV.SensorID))
                        select dV;
    dict.Add(Data, dValues.ToList<DataValue>());
}

但是这种方法存在严重的性能问题,需要很长时间才能执行。 不确定我是否需要使用SQL视图。有什么建议吗?

3 个答案:

答案 0 :(得分:4)

你的查询次数太多了。您可以在一个查询中执行此操作。

var dict = (from d in dt.Datas
            join dV in dt.DataValues on d.DataID equals dv.DataID
            where SensorIDs.Contains(dv.SensorID)
            select new { d, dV }).ToDictionary(o => o.d, o => o.dV.ToList());

foreach循环中,您正在获取所有Data,并且对于每个{0}},您正在做同样的事情。

编辑:现在还不是很清楚,但我想您只想加入SensorIDs数组中的DataValue。在这种情况下:

var dict = (from d in dt.Datas
            let dV = (from dataValue in dt.DataValues
                      where SensorIDs.Contains(dataValue.SensorID) &&
                            dataValue.DataID = d.DataID
                      select dataValue)
            select new { d, dV }).ToDictionary(o => o.d, o => o.dV.ToList());

答案 1 :(得分:1)

在这种情况下你不需要foreach循环,你可以使用group join直接从linq创建字典,这样可以提供更好的性能。

dict=(from DataValue d in dt.DataValues
           where sensorIDs.Contains(d.SensorID)
       group d by d.DataID 
           into datavalues
       join data in dt.Datas 
           on datavalues.Key equals data.DataId
       select new { 
         Key = data, 
         Value = datavalues
       }).ToDictionary(a=>a.Key,a=>a.Value.ToList());

或者你可以使用linq表达方法

dict = dt.DataValues.Where(d=>sensorIDs.Contains(d.SensorID))
            .GroupBy(a=>a.DataID)
             .Join(dt.Datas,a=>a.Key,a=>a.DataId,
                    (a,b)=>new{Key=b,Value=a.ToList()})
        .ToDictionary(a=>a.Key,a=>a.Value);

答案 2 :(得分:0)

你不需要foreach循环。通常尝试这样的事情:

var columns = dt.Columns.Cast<DataColumn>();
dt.AsEnumerable().Select(dataRow => columns.Select(column => 
                     new { Column = column.ColumnName, Value = dataRow[column] })
                 .ToDictionary(data => data.Column, data => data.Value));

另外,请考虑阅读:http://blogs.teamb.com/craigstuntz/2010/01/13/38525/