设置
映射
我有一个 MyItem 类,它有一个由 MyDetail 项组成的延迟加载集合:
[Serializable]
class MyItem : IComparable, ICloneable
{
public virtual int ID { get; set; }
}
[Serializable]
class MyDetail : ICloneable
{
public virtual int ID { get; set; }
public virtual MyItem EnclosingItem { get; set; }
}
void MyItemMap(IClassMapper<MyItem> ca)
{
ca.Lazy(false);
ca.Cache(cm => { cm.Usage(CacheUsage.NonstrictReadWrite); cm.Region(cacheRegion); });
ca.Id(x => x.ID, cm => { cm.Generator(Generators.Native); });
ca.Discriminator(cm => { cm.Column("Type"); cm.Type(NHibernateUtil.String); });
ca.Bag(x => x.Details, cm =>
{
cm.Key(k => k.Column("ItemID"));
cm.Inverse(true);
cm.Type<DetailFactory>();
cm.Cascade(Cascade.All | Cascade.DeleteOrphans);
cm.Fetch(CollectionFetchMode.Select);
cm.Lazy(CollectionLazy.Lazy);
cm.Cache(m => { m.Usage(CacheUsage.NonstrictReadWrite); });
} cr => cr.OneToMany());
}
void MyDetailMap(IClassMapper<MyDetail> ca)
{
ca.Lazy(true);
ca.Cache(cm => { cm.Usage(CacheUsage.NonstrictReadWrite); cm.Region(cacheRegion); });
ca.Id(x => x.ID, cm => { cm.Generator(Generators.Native); });
ca.ManyToOne(x => x.EnclosingItem, cm => { cm.Column("ItemID"); cm.NotNullable(true); cm.Fetch(FetchKind.Select); cm.Lazy(LazyRelation.Proxy); });
}
该系列
加载关联的 MyDetail 项的类是 PersistentGenericBag:
class DetailList : PersistentGenericBag<MyDetail>
{
}
采集工厂
这是通过自定义集合工厂发生的:
class DetailFactory : IUserCollectionType
{
public IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister)
{
return new DetailList(session);
}
public IPersistentCollection Wrap(ISessionImplementor session, object collection)
{
return new DetailList(session, (IList<MyDetail>)collection);
}
}
问题
假设我已经加载了一个 MyItem 并且我至少请求了一次详细信息,所以我的二级缓存 (SLC) 包含所有这些内容。还假设我只积极使用 1 个细节,而实际上有 100 个细节连接到 MyItem。这意味着,每当我从 SLC 访问 MyItem 并访问我感兴趣的一个细节时,整个集合都会实现:
// Get item coming from SLC
MyItem myItem = nhSession.Get(id);
// Access detail, materializing all MyDetails from SLC
MyDetail myDetail = myItem.Details["Interesting"];
// Normally, this last line will invoke the default NH proxy
// which then materializes the Details collections, fetching
// all details belonging to myItem from the database, or from
// the SLC for that matter.
//
// To cater for my scenario, I've got access to an interceptor
// to do my own processing (the details to how this is hooked
// up are not very relevant). This interceptor should somehow
// be able to, instead of initializing the collection, return
// the result from the SLC rightaway. This would prevent
// the materialization of possibly large collections.
解决优化问题
现在我想通过绕过集合加载来优化这个场景,并直接查询 SLC 以了解该细节的存在。请注意,我的问题不是从代码中截取实际的详细信息调用,而是干预以何种方式返回的内容。
我正在使用 SysCache,所以理论上我可以读出 ASP.NET 缓存,但由于缓存键是 NH 的实现细节,我不确定这是一个好主意。
有人给我指点吗?