ToList() занимает много времени при преобразовании IEnumerable с несколькими объектами
У меня есть следующие классы:
public class CountryVM
{
#region Properties
public int CountryID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
#endregion
#region Constructors
/// <summary>
/// Constructor
/// </summary>
public CountryVM()
{
}
/// <summary>
/// Constructor that creates a View Model based of an Entity object
/// </summary>
/// <param name="countryCode">Fills data to View Model</param>
public CountryVM(Country_Code countryCode)
{
if (countryCode != null)
{
CountryID = countryCode.Country_Code_ID;
Code = countryCode.Country_Code1;
Name = countryCode.Country_Name;
}
}
#endregion
}
public class StateVM
{
#region Properties
public int StateID { get; set; }
public int CountryID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public CountryVM Country { get; set; }
#endregion
#region Constructors
/// <summary>
/// Constructor
/// </summary>
public StateVM()
{
}
/// <summary>
/// Constructor that creates a View Model based of an Entity object
/// </summary>
/// <param name="stateCode">Fills data to View Model</param>
public StateVM(State_Code stateCode)
{
if (stateCode != null)
{
StateID = stateCode.State_Code_ID;
CountryID = stateCode.Country_Code_ID;
Code = stateCode.State_Code1;
Name = stateCode.State_Name;
Country = new CountryVM(stateCode.Country_Code);
}
}
#endregion
}
И Country_Code, и State_Code - это таблицы из моих таблиц, преобразованные в объекты Entity.
Я запускаю следующие строки кода:
IEnumerable<State_Code> entityList = _stateRepository.GetAllStateCodes();
IEnumerable<StateVM> viewModelList = entityList.Select(s => new StateVM(s));
viewModelList = viewModelList.ToList();
При беге
viewModelList = viewModelList.ToList();
это занимает от 1 до 3 секунд. Я экспериментировал с ним и удалил:
Country = new CountryVM(stateCode.Country_Code);
от объекта StateVM, и он будет работать без нареканий.
Итак, я полагаю, причина, по которой это занимает слишком много времени, заключается в том, что после создания экземпляра StateVM внутри него будет создан экземпляр CountryVM.
Есть ли способ, которым я могу улучшить производительность?
3 ответа
Запуск ToList() всегда будет перечислять коллекцию. То, с чем вы сталкиваетесь, - это все лениво загруженные свойства, которые ссылаются на другие таблицы, выполняющие сгенерированные операторы SQL, чтобы подобрать присоединенные свойства данных. Если они вам не нужны, вы должны отфильтровать свою коллекцию, пока не убедитесь, что у вас есть минимальный объем данных, необходимый для дальнейшей работы. Если вы знаете, что они вам понадобятся, вы можете использовать готовую загрузку, чтобы вместо этого загрузить все в исходном запросе, а не на объекте на объект на основе свойства. Взгляните на ObjectQuery.Include
Если вы используете Visual Studio 2013 Premium (или более поздний аналог), следите за окном отладчика Diagnostic Tools во время выполнения вашего кода. Трассировка даст вам хорошее представление о том, что происходит при извлечении ваших сущностей.
Распространенная ошибка - полагаться на ленивую загрузку по умолчанию Entity Framework, когда сущности имеют отношения к другим сущностям, по которым будет осуществляться навигация. В вашем случае вполне вероятно, что при выполнении запроса выполняются операторы N+1 SELECT - один для получения всех кодов состояния и один для каждого кода страны (оба State_Code
а также Country_Code
кажутся сущностями своих собственных).
Пожалуйста, обратитесь к Entity Framework Loading для дополнительных советов. Можно также выполнить поиск по "Entity Framework N+1", так как это частая причина проблем с производительностью.
Есть ли способ, которым я могу улучшить производительность?
Лучший способ повысить производительность - создать представление, содержащее только те столбцы, которые вам действительно нужны, включая любые объединения. Это позволит базе данных работать более эффективно и даст вам возможность использовать покрывающие индексы для еще большей производительности.
Второй лучший вариант - использовать.Include, как объясняется в ответе Джонатона Чейза.