[英]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.