在实现IEnumerable <t> </t>的类中,MoveNext的可怕性能

时间:2010-12-09 13:55:04

标签: .net ienumerable enumeration

我有一个在MVC应用程序中使用的包装器类,它设计用于遍历集合中的项目,并检查当前用户是否有权在返回该项目以进行显示之前访问该项目。在大多数情况下,它就像一个魅力。然而,对于一个特定的对象类型,它像绝对的狗一样运行,我无法弄清楚为什么。

接口类的编写方式如下:

    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() - 当然代码永远不会被命中?

问题出在我尝试在日志文件条目上使用此包装器时,这些条目通过LogEntryViewDaya类中的实体框架提供。当代码命中GetEnumerator中的foreach循环时,它会停止整整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看起来像任何东西一样光滑。

那么为什么这些特定对象的集合如此缓慢地迭代?我不知道:建议表示感谢。

1 个答案:

答案 0 :(得分:2)

您尚未向我们展示如何填充课程。我的 guess 是时间在进行数据库查询 - 特别是,根据所提取的内容,可能只有一个查询来获取骨架实体,然后每个查询一次 <{1}}和UserCanEdit。这似乎不太可能(我已经预料到条目会在初始查询中填充这些属性)但只是可能。

基本上,请观看它与您的数据库的交互方式。

我建议您尝试编写一个使用相同类的控制台应用程序,这样您就可以轻松搞定它,比Web应用程序更容易添加计时日志等。

编辑:除了评论中的其他内容之外,您是否有任何理由不将其作为LINQ查询的一部分?例如:

UserCanView

我很欣赏它可能不会那么简单,因为var query = db.LogEntries.Where(x => x.UserCanEdit || x.UserCanView); 将依赖于当前用户等 - 但它可能应该作为数据库查询而不是客户端。