2016-09-13 1 views
0

Мне нужно связать несколько сущностей. В настоящий момент код загружается первым сущностью, а затем повторяется с циклом foreach и выполняется поиск по каждой записи, если текущая строка соответствует свойству записи другого объекта. Что-то вроде:Лучшая производительность для поиска объектов в объектах и ​​объектах нагрузки, Foreach или где с LinQ ON C#?

foreach (Entity1 e1 in entity1List) 
    { 
    foreach (Entity2 e2 in entity2List) 
    { 
    if (e2.Id == e1.Id) 
    { 
    //Do something 
    } 
    } 
    } 

Но объекты имеют много записей и производительность не является хорошим. Я хочу улучшить скорость, пытаясь использовать linQ для поиска записи.

var list = entity2List.Where (e2 => entity1.Any (e1 => e1.Id == e2.Id));

foreach (Entity2 e2 in list) 
    { 
    //Do something 
    } 

Но я не знаю, действительно ли это помогает в производительности. Также я хотел бы знать лучшую модель для загрузки объектов в этом случае. Некоторые советы или ссылки для чтения или инструменты для сравнения времени исполнения, пожалуйста.

Я использую много соединений для загрузчиков каждой сущности, но они разделены, потому что при тестировании в других случаях строки много, и время от выполнения запроса в БД было слишком много, поэтому теперь объекты независимы, и я хочу создать зависимость по коду.

+0

вы всегда могли профиль как и выяснить. (Подсказка: загрузка меньшего количества записей, чем большие записи, всегда приведет к чистым выигрышам). –

+0

По какой причине вы не используете соединение? –

+1

И переключитесь с списка на HashSet или используйте словарь. Перемещение из списка в Hash/Dict будет существенно ускорять все поисковые запросы. –

ответ

0

Как @DavidL говорит, вы можете протестировать оба решения и посмотреть, что произойдет. Другой вариант - сделать хэш с первой коллекцией, а затем искать там ключ. Это должно повлиять на производительность.

Пример:

var e1ById = entity1List.GroupBy(x => x.Id).ToDictionary(x => x.Key); //you can skip the GroupBy if you know Id is a unique key) 

foreach(var e2 in entity2List.Where(x => e1ById.ContainsKey(e2.Id))) 
{ 
    //Do something 
} 

Или, может использовать список для хранения ключей:

var keys = entity1List.Select(x => x.Id).Distinct().ToList(); 

foreach(var e2 in entity2List.Where(x => keys.Contains(x.Id)) 
{ 
    //Do something 
} 

В любом случае, производительность зависит от исходной длины коллекции так попробовать различные решения и принять к сведению времена.

0

В целом, если производительность является вашей главной заботой, вы обычно лучше пишете собственный оптимизированный алгоритм. LINQ, конечно, будет медленнее, чем ваш оптимальный алгоритм из-за накладных расходов. Тем не менее, LINQ является элегантным и очень полезным для обслуживания кода. так что выбор за вами!

В данном конкретном случае, вы можете использовать Intersect() метода, который является более эффективным и проще, чем текущая реализация.

foreach (var element in entity1List.Intersect(entity2List)) 
{ 
// Do something 
} 
1

Если оба набора сущностей действительно перечислены, с помощью LINQ Where не даст вам повышение производительности, потому что это эквивалент текущего линейного алгоритма поиска с O (M * N) временной сложности.

Однако вы можете получить намного лучше, O (M + N) времени алгоритм сложности (таким образом, производительность) с помощью LINQ GroupJoin метод, который внутренне использует поиск на основе весьма эффективным хэш для корреляции двух последовательностей:

var list = from e1 in entity1List 
      join e2 in entity2List on e1.Id equals e2.Id into e2Group 
      select new { e1, e2Group }; 

foreach (var item in list) 
{ 
    var e1 = item.e1; 
    foreach (var e2 in item.e2Group) 
    { 
     //Do something 
    } 
} 

Если вам не нужен вложенная foreach цикла для обработки, вы можете использовать вместо Join, что даже нескольких более эффективным:

var list = from e1 in entity1List 
      join e2 in entity2List on e1.Id equals e2.Id 
      select new { e1, e2 }; 

foreach (var item in list) 
{ 
    var e1 = item.e1; 
    var e2 = item.e2; 
    //Do something 
} 
+0

Спасибо, что сравнил время моих методов с dotTrace и теперь лучше – UserEsp

Смежные вопросы