我正在使用Fluent NHibernate v2.0.50727构建一个ASP Web表单应用程序到SQL服务器后端。
由于某些原因,查询具有小数据(~14行)的表需要几秒钟。
地图非常简单:Id(x => x.Id)
和Map(x => x.Name)
。 CertificateGroup还有Map()的Color
和Rank
。
我已经隔离了用于测试的nhibernate代码:(这不是我的应用程序的代表,但是为了SO而被简化和隔离)
protected void Page_Load(object sender, EventArgs e)
{
var config = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("..."))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<PersonMap>()) .BuildConfiguration();
var factory = config.BuildSessionFactory();
using (var session = factory.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var departments = session.QueryOver<DepartmentModel>().List(); // these all take seconds to execute - this has 14 results
var jobs = session.QueryOver<JobModel>().List(); // 113 results
var certificates = session.QueryOver<CertificateModel>().List(); //this one about 4 seconds for 210 results
var groups = session.QueryOver<CertificateGroupModel>().List();
var association = new CertificateAssociationModel
{
Department = departments.First(),
Job = jobs.First(),
Certificate = certificates.First(),
Group = groups.First()
};
session.SaveOrUpdate(association);
transaction.Commit();
}
}
}
我将nhibernate交换为实体框架并运行上面的代码并且提取是即时的。
任何帮助表示感谢。
编辑:
以下是映射(如上所述): 部门,工作和证书:
public class DepartmentMap : ClassMap<DepartmentModel>
{
public DepartmentMap()
{
Table("tblDepartment");
Id(x => x.Id);
Map(x => x.Name);
}
}
CertificateGroupModel
也有
Map(x => x.Rank);
Map(x => x.Color);
实体类都是一样的:
public class CertificateModel
{
public virtual Int32 Id { get; protected set; }
public virtual String Name { get; set; }
}
除了CertificateGroupModel,它也有:
public virtual String Color { get; set; }
public virtual Int32 Rank { get; set; }
以下是我的NHiberate个人资料结果:
-- statement #1
begin transaction with isolation level: Unspecified
-- statement #2
SELECT this_.Id as Id4_0_,
this_.Name as Name4_0_
FROM tblDepartment this_
-- statement #3
SELECT this_.Id as Id5_0_,
this_.Type as Type5_0_
FROM tblJobTitles this_
-- statement #4
SELECT this_.Id as Id2_0_,
this_.Name as Name2_0_
FROM tblCertificate this_
-- statement #5
SELECT this_.Id as Id1_0_,
this_.Name as Name1_0_,
this_.Rank as Rank1_0_,
this_.Color as Color1_0_
FROM tbl_certificate_groups this_
-- statement #6
INSERT INTO lnk_certificate_associations
(Certificate_id,
Department_id,
Job_id,
Group_id)
VALUES (1 /* @p0 */,
1 /* @p1 */,
1 /* @p2 */,
1 /* @p3 */);
select SCOPE_IDENTITY()
-- statement #7
commit transaction
nhibprofile http://i.snag.gy/bTKHm.jpg
生成的IL代码:
var departments = session.QueryOver<DepartmentModel>().List();
IL_008F: ldloc.2 /* session */
IL_0090: callvirt instance NHibernate.IQueryOver`2<!!0, !!0> NHibernate.ISession::QueryOver<Core.Domain.Model.DepartmentModel>()
IL_0095: callvirt instance [mscorlib]System.Collections.Generic.IList`1<!0> NHibernate.IQueryOver`1<Core.Domain.Model.DepartmentModel>::List()
IL_009A: stloc.s departments
答案 0 :(得分:0)
猜测一下,因为你还没有在这里发布你的映射和表格......
您的数据库中是否有任何可以为空的列映射到不可为空的类型(例如,在模型中映射到int的nullable int)?
这会导致您看到的行为,因为当NHibernate加载您的实体时(让我们假设上面的DepartmentModel场景,属性Prop1是int),如果Prop1在数据库中为null,那么会话将会具有null的内部状态,但由于您无法将Prop1设置为null,因此将为其分配值0,并且当会话检查是否有任何更改时,它将看到Prop1已更改(从null更改为0),并且导致一大堆更新,这反过来会减慢很多事情。
如果是这种情况,解决方案是更新表定义或更新实体以获得正确(可为空)的类型。
有多种方法可以实现,我刚刚给出了一个简单的例子 - 如果你可以包含你的映射,表定义和实体类,它会有所帮助......
答案 1 :(得分:0)
至于插入问题,如果你正在使用Id的Identity生成器,那么nHibernate将首先要求数据库(INSERT...SELECT SCOPE_IDENTITY()
)为你的实体创建记录,然后用正确的Id和数据插入它({{1} })
请注意,其他实体的引用将在UPDATE
中更新,因为您只看到'?'在插入