首先让我说这是我使用NHibernate的第一个项目。
目前,我正在开发一个项目,该项目将在两个数据库之间同步数据,一个在本地计算机上,另一个在远程服务器上。它们都使用完全相同的模型/模式,其余的应用程序是使用NHibernate编写的,所以我试图在数据访问层保持一致。
到目前为止,一切似乎都运行得相当快,直到我点击了更大的数据集。它们无论如何都不是庞大的,桌子上有大约6000个条目,每个条目都有一对多的关系,热切的加载。与之相关的表格大约有30,000个条目。
当我最初触摸对象集合时,我的当前性能问题就出现了。即使没有操纵它,我也看到NHibernate有15-20秒的延迟来生成集合。当第二个集合生成时,我几乎看到了两倍。
这就是加载集合的函数:
private IQueryable<ProcessedEntity<T>> GetEntities(IStatelessSession session) {
var query = session.Query<T>();
return query.ToList<T>()
.ConvertAll<ProcessedEntity<T>>(e => new ProcessedEntity<T>(e))
.AsQueryable();
}
private class ProcessedEntity<T> {
public bool IsProcessed { get; set; }
public T Entity { get; set; }
public ProcessedEntity(T entity) {
this.IsProcessed = false;
this.Entity = entity;
}
}
这是我的班级地图:
public ProofMap() {
Schema("Prover");
Table("Proof");
Id(x => x.Id, "ProofId").GeneratedBy.Assigned();
Component(x => x.MeterData, cp => {
cp.Map(md => md.MeterId, "MeterId");
cp.Map(md => md.OperatorName, "MeterOperatorName");
cp.Map(md => md.LeaseDescription, "MeterLeaseDescription");
cp.Map(md => md.StationName, "MeterStationName");
cp.Map(md => md.Identifier, "MeterIdentifier");
cp.Map(md => md.Model, "MeterModel");
cp.Map(md => md.Manufacturer, "MeterManufacturer");
cp.Map(md => md.SerialNumber, "MeterSerialNumber");
cp.Map(md => md.Size, "MeterSize");
cp.Map(md => md.KFactor, "MeterKFactor");
cp.Map(md => md.MinFlowRate, "MeterMinFlowRate");
cp.Map(md => md.MaxFlowRate, "MeterMaxFlowRate");
cp.Map(md => md.AverageRuns, "MeterAverageRuns");
});
Component(x => x.ProverData, cp => {
cp.Map(pd => pd.ProverId, "ProverId");
cp.Map(pd => pd.Manufacturer, "ProverManufacturer");
cp.Map(pd => pd.Type, "ProverType");
cp.Map(pd => pd.SerialNumber, "ProverSerialNumber");
cp.Map(pd => pd.Volume, "ProverVolume");
cp.Map(pd => pd.CalibrationDate, "ProverCalibrationDate");
cp.Map(pd => pd.InnerDiameter, "ProverInnerDiameter");
cp.Map(pd => pd.WallThickness, "ProverWallThickness");
cp.Map(pd => pd.ThermalExpansion, "ProverThermalExpansion");
cp.Map(pd => pd.Elasticity, "ProverElasticity");
});
Component(x => x.PreviousProofData, cp => {
cp.Map(ppd => ppd.ProofId, "PreviousProofId");
cp.Map(ppd => ppd.Date, "PreviousProofDate");
cp.Map(ppd => ppd.MeterFactor, "PreviousProofMeterFactor");
cp.Map(ppd => ppd.Gravity, "PreviousProofGravity");
cp.Map(ppd => ppd.Temperature, "PreviousProofTemperature");
cp.Map(ppd => ppd.Rate, "PreviousProofRate");
cp.Map(ppd => ppd.TotalCounts, "PreviousProofTotalCounts");
});
Map(x => x.UserId);
Map(x => x.DateTime);
Map(x => x.Ctsp);
Map(x => x.Cpsp);
Map(x => x.Ctlp);
Map(x => x.Cplp);
Map(x => x.Ctlm);
Map(x => x.Cplm);
Map(x => x.Cpll);
Map(x => x.ProverVolume, "ProofProverVolume");
Map(x => x.NetProverVolume);
Map(x => x.AveragePulses);
Map(x => x.PulsesPerUnit);
Map(x => x.GrossMeterVolume);
Map(x => x.NetMeterVolume);
Map(x => x.MeterFactor);
Map(x => x.CompositeMeterFactor);
Map(x => x.Gravity);
Map(x => x.Temp);
Map(x => x.AmbientTemp);
Map(x => x.PassedValidation);
Map(x => x.BlockBleedChecked);
Map(x => x.IsOfficial);
Map(x => x.LastUpdatedDateTime);
Map(x => x.CurrentTotals);
Map(x => x.ProofNumber);
HasMany(x => x.Runs).KeyColumn("ProofId")
.Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore)
.Fetch.Join()
.Cascade.AllDeleteOrphan()
.Not.LazyLoad();
}
public RunMap() {
Schema("Prover");
Table("Run");
Id(x => x.Id, "RunId").GeneratedBy.Assigned();
References(x => x.Proof, "ProofId");
Map(x => x.DateTime);
Map(x => x.RunNumber);
Map(x => x.IsAverageForProof);
Map(x => x.ForwardCounts);
Map(x => x.ReverseCounts);
Map(x => x.RoundCounts);
Map(x => x.FlowRate);
Map(x => x.MeterTemp);
Map(x => x.ProverTemp);
Map(x => x.MeterPress);
Map(x => x.ProverPress);
Map(x => x.LastUpdatedDateTime);
}
我应该提一下,目前这两个数据库都在我的本地机器上进行测试。我尝试使用foreach循环来执行ConvertAll操作,并观察到相同类型的延迟。
关于如何在这里提高NHibernate性能的任何想法?
编辑:
我的问题在于GetEntities功能。查询将立即加载。但是没有信息,那么当我触摸ConvertAll内部的集合时,我已经尝试了一个具有完全相同结果的foreach循环,它将导致NHibernate从DB生成集合,即延迟发生时。