2013-06-26 5 views
2

Я искал, как присоединиться к двум таблицам (Data and DataValues, от одного до многих) и заполнить словарь типа.Соедините две таблицы, используя linq, и заполните их Слова

Записи данных могут составлять тысячи (например, 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-представления. какие-либо предложения?

+0

Насколько велика ваша DataTable? – Learner

+0

около 1200 записей в день (только для данных), и каждая информация может содержать от 5 до 18 DataValue. текущая строка таблицы «Данные» равна 125,361 – Arman

+0

. Ваш запрос также неверен, вы должны сделать выбор на 'dt.DataValues' и включить проверку Data.DataID == dV.DataID, а также в свою 'where' – konkked

ответ

3

Вы запрашиваете слишком много раз. Вы можете сделать это в одном запросе.

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 и для каждого из них, вы делаете то же самое.

Редактировать: Теперь это было не очень ясно, но я думаю, вы хотите присоединиться только к DataValue s, которые находятся в массиве SensorIDs. В этом случае:

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()); 
+0

Без четкого представления о том, как' Data', 'DataValue' и' SeonsorID' связаны друг с другом в его модели и/или базе данных, я не могу сказать точно. Но «Содержит» с массивом в Entity Framework преобразуется в инструкцию 'IN (.. the values ​​in the array ..)'. Поэтому, если массив, который он делает «Содержит», очень большой, он имеет очень небольшое влияние на производительность. –

+0

Ну, спасибо, но возвращаемый тип - это словарь типа , в то время как я хочу иметь <данные, список > (внимание на список!) – Arman

+1

См. Отредактированный ответ –

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/

1

Вам не нужно foreach цикл в этом случае, вы можете использовать группу присоединиться для создания словаря прямо из 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);