我有一些我不明白的行为。我正在使用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);
}
}
以下是调用上述方法的地方:
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();
}
}
答案 0 :(得分:5)
首先,如果您将所有IList交换出来并用IEnumerables替换,那么这不是一个小改动。主要区别在于可以使用您的IEnumerables延迟执行,而在使用IList时您总是急切执行。如果您不了解这种差异,这可能会导致很多问题。
在您的情况下,差异的原因是延迟执行和RavenDB的.Include<T>()
功能的错误使用的组合。后者旨在通过在客户端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);
}