0

セットアップ

マッピング

MyDetail 項目で構成される遅延ロードされたコレクションを持つ MyItem クラスがあります。

[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 をロードし、Details を少なくとも 1 回要求したとします。したがって、2 番目のレベルのキャッシュ (SLC) にはこれらすべてが含まれています。また、実際には 100 個の詳細が MyItem に接続されているのに、1 つの詳細のみをアクティブに使用しているとします。これは、SLC から MyItem にアクセスし、関心のある 1 つの詳細にアクセスするたびに、コレクション全体が具体化されることを意味します。

// 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 の実装の詳細であるため、それが良い考えかどうかはわかりません。

誰か私へのポインタを持っていますか?

4

1 に答える 1