[英]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;
以下代碼使我感到困惑。 當我使用調試器逐步調試時,會急切加載Unit
的Parts
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.5的batch-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.