我有一个在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看起来像任何东西一样光滑。
那么为什么这些特定对象的集合如此缓慢地迭代?我不知道:建议表示感谢。
答案 0 :(得分:2)
您尚未向我们展示如何填充课程。我的 guess 是时间在进行数据库查询 - 特别是,根据所提取的内容,可能只有一个查询来获取骨架实体,然后每个查询一次 <{1}}和UserCanEdit
的。这似乎不太可能(我已经预料到条目会在初始查询中填充这些属性)但只是可能。
基本上,请观看它与您的数据库的交互方式。
我建议您尝试编写一个使用相同类的控制台应用程序,这样您就可以轻松搞定它,比Web应用程序更容易添加计时日志等。
编辑:除了评论中的其他内容之外,您是否有任何理由不将其作为LINQ查询的一部分?例如:
UserCanView
我很欣赏它可能不会那么简单,因为var query = db.LogEntries.Where(x => x.UserCanEdit || x.UserCanView);
将依赖于当前用户等 - 但它可能应该作为数据库查询而不是客户端。