NHibernate与C#无状态会话加载性能问题

时间:2012-12-11 19:11:05

标签: c# performance nhibernate fluent-nhibernate

首先让我说这是我使用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生成集合,即延迟发生时。

0 个答案:

没有答案