2010-12-09 1 views
0

У меня есть класс-оболочка, который используется в приложении MVC, который предназначен для циклического перемещения элементов в коллекции и проверки того, что у текущего пользователя есть авторизация для доступа к этому элементу перед возвратом это для отображения. По большей части это работает как шарм. Однако для одного конкретного типа объекта он работает как абсолютная собака, и я не могу понять, почему.Ужасная производительность MoveNext внутри класса, реализующего IEnumerable <T>

классы

Интерфейс записываются так:

private readonly IEnumerable<T> _ViewData; 

    public IEnumerator<T> GetEnumerator() 
    { 
     foreach (T item in _viewData) 
     { 
      if (item.UserCanEdit || item.UserCanView) 
       yield return item; 
     } 
    } 


    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

Теперь мой первый вопрос, это проверить мое понимание того, что здесь происходит. Я, вероятно, ошибаюсь, но я понимаю, что когда я пытаюсь запустить цикл foreach против коллекции объектов типа, ему никогда не нужно использовать System.Collections.IEnumerable.GetEnumerator() - неужели этот код никогда не попадает?

Проблема заключается в том, что я пытаюсь использовать эту оболочку для записей в файле журнала, которые доставляются через сущность framework в классе LogEntryViewDaya. Когда код попадает в цикл foreach внутри GetEnumerator, он останавливается на полные 6-8 секунд, хотя в перечислении всего 20 элементов!

Вот код для LogEntryView

public class LogEntryViewData:BaseViewData 
{ 
    private LogEntry _entry; 
    public LogEntryViewData(LogEntry entry, ICustomerSecurityContext securityContext) : base(securityContext) 
    { 
     _entry = entry; 
    } 

    public string Application { get { return _entry.Application; } } 
    public string CurrentUser { get { return _entry.CurrentUser; } } 
    public string CustomerName { get { return _entry.CustomerName; } } 
    public DateTime Date { get { return _entry.Date; } } 
    public string Exception { get { return _entry.Exception; } } 
    public string HostName { get { return _entry.HostName; } } 
    public long Id { get { return _entry.Id; } } 
    public string Level { get { return _entry.Level; } } 
    public string Message { get { return _entry.Message; } } 
    public int? ProcessId { get { return _entry.ProcessId; } } 
    public int? ServiceId { get { return _entry.ServiceId; } } 
    public string ServiceName { get { return _entry.ServiceName; } } 
    public int? TaskId { get { return _entry.TaskId; } } 
    public int? TaskName { get { return _entry.TaskName; } } 
    public string Thread { get { return _entry.Thread; } } 
} 

Насколько я могу сказать, что нет никакой заметной производительности в инстанцировании этих классов - положить точку останова в конструкторе и F5ing через кажется гладкая, как и все.

Итак, почему коллекция этих конкретных объектов настолько медленна, чтобы проходить через итерацию? Я понятия не имею: предложения с благодарностью оценили.

ответ

2

Вы не показали нам, как заполняется класс. Мой догадка заключается в том, что время идет по запросам базы данных - в частности, в зависимости от того, что выберет, просто возможно, что есть один запрос для получения скелетных объектов, а затем один запрос для каждый из UserCanEdit и UserCanView. Это кажется маловероятным (я бы ожидал, что запись будет иметь эти свойства, заполненные первоначальным запросом), но просто возможно.

В основном, посмотрите, как он взаимодействует с вашей базой данных.

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

EDIT: Помимо всего прочего в комментариях и т. Д., Есть ли причина, по которой вы не делаете это как часть запроса LINQ? Например:

var query = db.LogEntries.Where(x => x.UserCanEdit || x.UserCanView); 

Я ценю это, вероятно, не будет столь же просто, как, что, как UserCanEdit будет зависеть от текущего пользователя и т.д. - но это, вероятно, должны быть сделано как запрос к базе данных, а не клиент- боковая сторона.

+0

Хорошо, я покажу свое невежество, но я предположил, что класс был заселен, когда его конструктор был вызван? Это происходит до того, как он когда-либо попадает в петлю foreach и, кажется, происходит с удовлетворительной скоростью. – 2010-12-09 14:11:55