C# 有人知道我为什么从NHibernate/NH Profiler收到这个警告吗?

C# 有人知道我为什么从NHibernate/NH Profiler收到这个警告吗?,c#,.net,nhibernate,lazy-loading,nhprof,C#,.net,Nhibernate,Lazy Loading,Nhprof,禁用了完全限定的类型名称的惰性属性获取,因为它在实体级别不支持惰性 NH事件探查器报告了此警告,因此,我正在经历可怕的选择N+1副作用。因此,如果返回2200个子组实体,将执行另一个查询以检索每个InvoicePreference实体2201查询总数。这种关系似乎是问题的根源 下面是讨论中的实体及其各自的映射 实体1 映射1 地图2 InvoicePreference被引用为hasone。由于默认情况下它是lazyloaded,所以NHibernate将创建一个代理来填充属性InvoicePre

禁用了完全限定的类型名称的惰性属性获取,因为它在实体级别不支持惰性

NH事件探查器报告了此警告,因此,我正在经历可怕的选择N+1副作用。因此,如果返回2200个子组实体,将执行另一个查询以检索每个InvoicePreference实体2201查询总数。这种关系似乎是问题的根源

下面是讨论中的实体及其各自的映射

实体1

映射1

地图2


InvoicePreference被引用为hasone。由于默认情况下它是lazyloaded,所以NHibernate将创建一个代理来填充属性InvoicePreference,并为此需要InvoicePreference中不在子组中的标识。因此,它必须使用propertyref中的属性查询它


为了解决这个问题,do.Not.LazyLoad和/或.Fetch.Join

我想NH禁用实体级别的延迟加载是有原因的,我理解为不创建代理。这可能有几个原因。你以前收到过另一个警告吗?我真的不明白为什么它禁用了惰性属性,这意味着有些属性是惰性加载的。这是映射中显式使用的功能,但在映射定义中我看不到类似的内容


要克服N+1,可以使用Fetch.Join。我在这方面的经验不好,因为查询变得非常大。在复杂模型中,您可能会遇到一些数据库服务器限制,例如查询的最大列数。最好使用批处理大小,这样可以显著减少查询数量。看看。

这是NH profiler发出的确切信息吗?不是确切的信息。它具有类型的实际名称。警告:禁用了Neb.RetirementStatements.Services.Domain.Subgroup的惰性属性获取,因为它在实体级别不支持惰性,这似乎与此问题有关。事实上,我根本不想让它进行快速加载。我不想加载实体,因为我没有将其用于请求。我甚至都没碰那房子。我当然在使用AutoMapper,但据我所知,它也不涉及属性,因为它没有在正在执行的映射中使用。如果您不想立即加载,请不要关闭它。不要提取。加入并使用批大小。我不知道你为什么得到这个警告。您可能会问NH剖析器论坛/支持站点。谢谢Stefan。我知道如何进行快速加载以及获取策略的细微差别,但实际上我不想对该属性/关联做任何事情。我根本没有尝试加载/访问它。如果是这样的话,那么是的,我想急切地加载它。我只是想知道为什么它特别想延迟加载这种关系。我不会访问该财产或任何其他财产,如员工和管理员。为什么它对另外两种关系不起同样的作用?它还应该尝试延迟加载员工和管理员。其他两个是集合,而InvoicePreference不是集合,这是事实吗?难道他们不应该表现得一模一样吗?在我访问这些属性之前,NHibernate不应该尝试加载它们。这是你解释的另一种说法吗?property ref:延迟加载仅对对象id有效。当通过目标实体中的不同列解析属性关联时,NH会急切地获取它。并不是说这不可能,只是没有实现:Bugit不可能延迟加载它,因为正如我所说的,创建代理NH需要引用实体的标识,而此时它没有。这不是bug,而是使用property-ref时的折衷方法。使用select子句并直接将数据投影到所需的属性中,这是一种可以采用的方法,但在这一点上,我将颠倒关联。从子组中删除InvoicePreference,去掉映射,并在InvoicePreference中引用子组。因此,我将把SubgroupId从Guid重构为实际的子组类型。在这一点上,这对我来说是最简单、最有效的事情。谢谢你的建议。
public class Subgroup : Entity
{
     public virtual string GroupNumber { get; set; }

     public virtual string RUSNumber { get; set; }

     public virtual string REANumber { get; set; }

     public virtual string CustomerType { get; set; }

     public virtual string Name { get; set; }

     public virtual IList<IndividualEmployment> Employees { get; set; }

     public virtual IList<BenefitsAdministrator> Administrators { get; set; }

     public virtual InvoicePreference InvoicePreference { get; set; }
}
public class InvoicePreference : IEntity
{
    public virtual Guid Id { get; set; }

    public virtual Guid SubgroupId { get; set; }

    public virtual bool PaperlessNotifications { get; set; }
}
public static AutoPersistenceModel ConfigureSubGroup(this AutoPersistenceModel 
autoPersistenceModel)
{
    return autoPersistenceModel.Override<Subgroup>(map =>
    {
        map.Table("SubgroupV");

        map.Id(s => s.Id).Column(SubGroupPrimaryKeyColumn);

        map.Map(s => s.CustomerType, "BAS_Customer_Type");
        map.Map(s => s.RUSNumber, "BAS_RUS_Number");
        map.Map(s => s.GroupNumber, "BAS_Group_Number");
        map.Map(s => s.REANumber, "BAS_REA_Number");

        map.HasMany(s => s.Administrators).KeyColumn(SubGroupPrimaryKeyColumn);
        map.HasMany(s => s.Employees).KeyColumn(SubGroupPrimaryKeyColumn);
        map.HasOne(s => s.InvoicePreference).PropertyRef(i => i.SubgroupId);
    });
}
public static AutoPersistenceModel ConfigureInvoicePreference(this AutoPersistenceModel autoPersistenceModel)
{
    return autoPersistenceModel.Override<InvoicePreference>(map =>
    {
        map.Table("SubgroupInvoicePreference");
        map.Schema(RetirementStatementsSchemaName);
    });
}