簡體   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