2

我正在使用 Fluent NHibernate v2.0.50727 构建一个到 SQL 服务器后端的 ASP Web 表单应用程序。

出于某种原因,查询具有小数据(~14 行)的表需要几秒钟的时间。

地图都很简单:Id(x => x.Id)Map(x => x.Name)。CertificateGroup 也是 Map() 的ColorRank.

我已经隔离了用于测试的 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; }

这是我的 NHirate 分析器结果:

 -- 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
4

2 回答 2

0

至于插入问题,如果您使用Identity generator for Id,那么nHibernate将首先要求数据库(INSERT...SELECT SCOPE_IDENTITY())为您的实体创建记录,然后使用正确的Id和数据(UPDATE)插入它

请注意,对其他实体的引用将在其中更新,UPDATE因此您只能看到“?” 在插入

于 2013-06-12T13:05:09.433 回答
0

At a guess, since you haven't posted your mappings and tables here...

Do you have any nullable columns in your database that are mapped to not-nullable types (eg. nullable int mapped to int in your model)?

This can cause the sort of behaviour you're seeing because when NHibernate loads your entities (let's assume the above scenario for DepartmentModel, with a property Prop1 that's an int), if Prop1 is null in the database, then the session will have an internal state for null, but since you cant set Prop1 = null, it will be assigned a value of 0, and when the session checks if anything has changed, it will see that Prop1 has changed (from null to 0), and cause a whole bunch of updates, which will in turn slow things down a lot.

The solution if this is the case would be to either update your table definitions or update your entities to have the correct (nullable) types.

There are various ways this can happen, I've just given a simple example - it would help if you could include your mappings, table definitions and entity classes...

于 2013-06-12T12:59:09.020 回答