Bob*_*orn 1 linq ienumerable ravendb
我有一些我不理解的行为.我正在使用RavenDB,我正在为每个工作单元使用一个会话:当逻辑类调用RavenDB数据访问层(DAL)时,会创建一个新会话.在DAL中,可以调用其他DAL类和方法,但只使用一个会话.
我不明白的部分是在下面的GetMostRecentByStartTime()方法中使用IEnumerable和List之间的区别.在该方法中,使用List就像显示的一样,这是我的输出:
使用List:
关闭会话之前
的请求数:2 关闭会话之前
的请求数:4 关闭会话之前
的请求数:6 关闭会话之前的请求数:7
注意:会话实际上并未在每个时间关闭; 只在最后一次之后.我们只在完成最初调用的DAL方法时关闭会话.
现在,如果我用IEnumerable替换List的每个实例(这是我做的唯一更改),我得到这个输出:
使用IEnumerable:
关闭会话之前
的请求数:2 关闭会话之前
的请求数:3 关闭会话之前
的请求数:4 关闭会话之前的请求数:27
为什么不同?
另一个问题是,当我在我的应用程序中添加新的InstallationSummary对象时,使用IEnumerable方法增加了请求计数.我不明白为什么.当我使用List方法时,即使添加了更多的InstallationSummary对象,请求计数也保持不变.也有人可以解释一下吗?
public IEnumerable<InstallationSummary> GetMostRecentByStartTime(int numberToRetrieve)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
try
{
return ExecuteQuery<IEnumerable<InstallationSummary>>(() =>
{
List<InstallationSummary> installationSummaries =
QueryAndCacheEtags(session => session.Advanced.LuceneQuery<InstallationSummary>()
.Include(x => x.ApplicationServerId)
.Include(x => x.ApplicationWithOverrideVariableGroup.ApplicationId)
.Include(x => x.ApplicationWithOverrideVariableGroup.CustomVariableGroupId)
.OrderByDescending(summary => summary.InstallationStart)
.Take(numberToRetrieve)).Cast<InstallationSummary>().ToList();
List<string> appServerIds = (from item in installationSummaries select item.ApplicationServerId).ToList();
List<string> appIds = (from item in installationSummaries select item.ApplicationWithOverrideVariableGroup.ApplicationId).ToList();
List<string> groupIds = (from item in installationSummaries select item.ApplicationWithOverrideVariableGroup.CustomVariableGroupId).ToList();
List<ApplicationServer> appServers = new ApplicationServerData().GetByIds(appServerIds).ToList();
List<Application> apps = new ApplicationData().GetByIds(appIds).ToList();
List<CustomVariableGroup> groups = new CustomVariableGroupData().GetByIds(groupIds).ToList();
foreach (InstallationSummary summary in installationSummaries)
{
summary.ApplicationServer = appServers.Where(server => server.Id == summary.ApplicationServerId).FirstOrDefault();
summary.ApplicationWithOverrideVariableGroup.Application =
apps.Where(app => app.Id == summary.ApplicationWithOverrideVariableGroup.ApplicationId).FirstOrDefault();
if (summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId == null) { continue; }
summary.ApplicationWithOverrideVariableGroup.CustomVariableGroup =
groups.Where(group => group.Id == summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId).FirstOrDefault();
}
return installationSummaries;
});
}
finally
{
stopwatch.Stop();
Debug.WriteLine("InstallationSummaryData.GetMostRecentByStartTime(): " + stopwatch.ElapsedMilliseconds);
}
}
Run Code Online (Sandbox Code Playgroud)
以下是调用上述方法的地方:
protected T ExecuteQuery<T>(Func<T> func)
{
if (func == null) { throw new ArgumentNullException("func"); }
try
{
return func.Invoke();
}
finally
{
Debug.WriteLine("Number of requests just before closing session: " + _session.Advanced.NumberOfRequests);
CloseSession();
}
}
Run Code Online (Sandbox Code Playgroud)
首先,如果您将所有IList交换出来并替换为IEnumerables,那么这不是一个小改动.主要区别在于您可以使用IEnumerables获得延迟执行,而使用IList时始终执行急切执行.如果您不了解这种差异,这可能会导致很多问题.
在您的情况下,差异的原因是延迟执行和.Include<T>()RavenDB功能的错误使用的组合.后者旨在通过在客户端DocumentSession中缓存包含的文档来减少对数据库的远程调用次数.如果您使用DocumentSession.Load<T>()它,这种方法很有用,但如果您使用文档,则没有任何区别DocumentSession.Query<T>().Where(x => x.Id == id).如果您熟悉NHibernate,这是您的第一级缓存.
为了使其正常工作,请更改代码并使用此代码:
List<InstallationSummary> installationSummaries =
QueryAndCacheEtags(session => session.Advanced.LuceneQuery<InstallationSummary>()
.Include(x => x.ApplicationServerId)
.Include(x => x.ApplicationWithOverrideVariableGroup.ApplicationId)
.Include(x => x.ApplicationWithOverrideVariableGroup.CustomVariableGroupId)
.OrderByDescending(summary => summary.InstallationStart)
.Take(numberToRetrieve)).Cast<InstallationSummary>().ToList();
foreach (InstallationSummary summary in installationSummaries)
{
summary.ApplicationServer = session.Load<ApplicationServer>(summary.ApplicationServerId);
summary.ApplicationWithOverrideVariableGroup.Application =
session.Load<Application>(summary.ApplicationWithOverrideVariableGroup.ApplicationId);
if (summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId != null)
summary.ApplicationWithOverrideVariableGroup.CustomVariableGroup =
session.Load<CustomVariableGroup>(summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
643 次 |
| 最近记录: |