繁体   English   中英

NHibernate只积极加载Dictionary <map> 单步执行代码时

[英]NHibernate only eagerly loads Dictionary <map> when stepping through code

我有一个带Parts Dictionary的班级Unit 映射看起来像这样

<class name="Unit" table="Units">
<id name="Id">
  <generator class="native"/>
</id>
<property name="CreationDate" />

<property name="MacAddress" />
<property name="OEMId" />
<property name="SerialNumber" />
<property name="QualityControlState" />

<map name="Parts" table="UnitParts" lazy="false">
  <key column="UnitId"/>
  <index column="TypeOfPart" type="integer"/>
  <composite-element class="UnitPart">
    <property name="PartInfo"/>
    <property name="Remarks"/>
  </composite-element>
</map>

当我Session.SaveOrUpdate(Unit)一切顺利时:两个表中填充正确的数据。 并且该单元也可以使用Session.Get(typeof(Unit) )进行Session.Get(typeof(Unit)及其所有Parts )。

问题:延迟获取多个单元会加载Parts Dictionary

该问题用伪代码改写: LoadMethodOfPartsDictionary = (Stepping with Debugger) ? Eagerly : Lazy; LoadMethodOfPartsDictionary = (Stepping with Debugger) ? Eagerly : Lazy;

以下代码使我感到困惑。 当我使用调试器逐步调试时,会急切加载UnitParts Dictionary 但是当我运行return Units (而不是逐步执行Units = crit.Future<Unit>().ToList<Unit>(); )时,NHibernate似乎希望延迟加载,因为Parts Dictionary突然是NHibernate.Collection.Generic.PersistentGenericMap

/// <summary>
/// Retreives a list of units by a set of criteria.
/// </summary>
/// <returns>A list of units that fall within/match the criteria</returns>
public static List<Unit> GetUnits(List<KeyValuePair<Unit.SortableProperties, ListSortDirection>> SortColumnOrder, out uint NumberOfRecordsWithoutLimit, uint Start = 0, int End = -1, FilterUnits Filter = default(FilterUnits))
{
    List<Unit> Units = default(List<Unit>);

    NumberOfRecordsWithoutLimit = 0;
    using (ISession Session = ORM.SessionFactory.OpenSession())
    {
        using (ITransaction Transaction = Session.BeginTransaction())
        {
            ICriteria crit = Session.CreateCriteria<Unit>();

            //Limit result set, used for paging
            if (End > 0)
            {
                crit.SetFirstResult((int)Start);
                crit.SetMaxResults(End);
            }

            //TODO: Implement filter code here

            //Add the sort order
            foreach (KeyValuePair<Unit.SortableProperties, ListSortDirection> kvp in SortColumnOrder)
            {
                String PropertyName = "";
                switch (kvp.Key)
                {
                    case Unit.SortableProperties.PRODUCTIONDATE:
                        PropertyName = "CreationDate";
                        break;
                    default:
                        throw new NotImplementedException(kvp.Key.ToString() + " isn't implemented for sorting yet.");
                }
                crit.AddOrder(new Order(PropertyName, (kvp.Value == ListSortDirection.Ascending)));
            }

            if (End > 0)
            {
                //Count the total units available in database.
                Units = crit.Future<Unit>().ToList<Unit>(); //This seems to lazy load the Units
                IFutureValue<int> RowCount = Session.CreateCriteria<Unit>()
                                        .SetProjection(Projections.Count(Projections.Id()))
                                        .FutureValue<int>();
                NumberOfRecordsWithoutLimit = (uint)RowCount.Value;
            }
            else
            {
                Units = (List<Unit>)crit.List<Unit>();
                NumberOfRecordsWithoutLimit = (uint)Units.Count;
            }

            Transaction.Commit();
            Session.Close();
            return Units;
        }
    }
}

任何提示表示赞赏。

PS我使用[Debugging]标签,因为在这种情况下这似乎很关键。

如何从数据库中接收数据有两种不同的概念。 如果是一对多(列表,字典)。

1)我们可以调用NHibernate通过ID或引用获取数据(类似情况)

session.Get<Unit>(1);

在这种情况下,NHibernates注入所有标记为lazy的属性。 因此,在您的情况下,这也将导致零件的急切加载。

参考属性类似: public virtual Unit Unit { get; set; } public virtual Unit Unit { get; set; } public virtual Unit Unit { get; set; } ANE的OtherObject

var otherObject = ... // get from session
var unit = otherObject.Unit; // the full Unit with all `Lazy="false"` properties is loaded

2)但是我们也可以使用Criteria (根据您的情况)。 但是,这是不同的方法。 在这种情况下,我们明确地说我们只希望与Unit

Units = crit.Future<Unit>().ToList<Unit>();

这具有许多优点:

  • 我们只能在Unit表上进行有效的分页
  • 仅加载单元(也许不使用零件)
  • 如果使用零件,它们将被延迟加载

但是,如果确实需要(不正确的分页之类的副作用),我们也可以选择加载部件:

Units = crit
  .SetFetchMode("Parts", FetchMode.Eager)
  .Future<Unit>()
  .ToList<Unit>();

现在全部填充一次。

3)我要投票的方法(我正在使用100%)是让collection变得懒惰,并分配19.1.5batch-size 使用批量提取

EXTENDED

向您展示如何更改映射:

<map name="Parts" table="UnitParts" lazy="true" batch-size="25">

从那时起,您的Util变得轻巧。 直到真正需要时才加载零件。 如果在整个请求期间都打开了会话,则在触摸部件后,它们将被加载到一个SELECT中(如果Utils的页面大小不大于25)

这种方法非常有效,因为它使用了ORM的功能-一切都很懒惰

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM