caching - NHibernate SysCache 不缓存子对象

标签 caching nhibernate syscache

希望得到您的帮助。 我有简单的主子集(“player”和“playerChildObject”)。获取“玩家”也会获取其链接的子项。

SysCache 会缓存播放器,但不会缓存子级。

以下是对象(均使用 Cache.ReadWrite() 设置):

实体:

public class Player
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<PlayerChildObject> PlayerChildObjects { get; set; }

    public Player()
    {
        PlayerChildObjects = new List<PlayerChildObject>();
    }
}

public class PlayerChildObject
{
    public virtual int Id { get; protected set; }
    public virtual Player Player { get; set; }
}

映射:

public class PlayerMap : ClassMap<Player>
{
    public PlayerMap()
    {
        Id(x => x.Id).Column("id");
        Map(x => x.Name).Column("name");
        HasMany(x => x.PlayerChildObjects).KeyColumn("PlayerId")
            .Inverse()
            .Cascade.All()
            .Not.LazyLoad();
        Table("accounts");
        Cache.ReadWrite();
    }
}

public class PlayerChildObjectMap : ClassMap<PlayerChildObject>
{
    public PlayerChildObjectMap()
    {
        Id(x => x.Id).Column("id");
        References<Player>(x => x.Player, "playerId");
        Table("playerChildObjects");
        Cache.ReadWrite();
    }
}

session 工厂还带有“UseQueryCache”和“UseSecondLevelCache”:

Fluently.Configure()
.Database(MySQLConfiguration.Standard.ConnectionString(cs => ...))
.Cache(c => c.UseQueryCache().UseSecondLevelCache()
.ProviderClass(typeof (NHibernate.Caches.SysCache.SysCacheProvider).AssemblyQualifiedName))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<PlayerChildObjectMap>())
.BuildSessionFactory();

查询本身使用 SetCacheable(true).SetCacheMode(CacheMode.Normal):

using (var session = SessionFactory.OpenSession())
{
    using (var transaction = session.BeginTransaction())
    {
        players = session.CreateCriteria(typeof(Player))
            .SetCacheable(true)
            .SetCacheMode(CacheMode.Normal)
            .List<Player>();
        transaction.Commit();
    }
}

但是,分析器显示玩家已被缓存(仅在第一次执行玩家获取代码时调用),而每次通过 PlayerID 检索相同的 PlayerChildObjects。

因此,第一个请求给出 N+1 个 DB 调用(玩家列表 + 每个玩家的子对象),所有连续请求执行 N 个调用(每个玩家的子对象)。

我错过了什么? 如何让SysCache也缓存子级?

SysCache版本:3.1.0.4000

最佳答案

我想说,有两个问题。首先,即使是一对多(HasMany)也有缓存设置:

HasMany(x => x.PlayerChildObjects).KeyColumn("PlayerId")
    ...
    .Cache.IncludeAll() // or .IncludeNonLazy, .CustomInclude("customInclude")
        .ReadOnly() // or .NonStrictReadWrite(), .ReadWrite(), .Transactional(),
                    //  .CustomUsage("customUsage")        
        .Region("regionName");

查看更多有关 HasMany mapping here 的信息(Adam Bar 撰写的关于通过代码映射的文章,但最后是流畅的)

文档 19.2.1. Cache mappings

其次,我们应该使用批量获取:

public PlayerMap()
{
    BatchSize(25);

    HasMany(x => x.PlayerChildObjects).KeyColumn("PlayerId")
        ...
        .BatchSize(25)
...
public PlayerChildObjectMap()
{
    BatchSize(25);
    ...

在文档 19.1.5. Using batch fetching 中了解更多相关信息,或在这里:

关于caching - NHibernate SysCache 不缓存子对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29667925/

相关文章:

performance - 为什么使用外部循环比使用内部循环更快地迭代外部维度?

c# - 为什么 Directory.GetFiles() 在后续运行中运行得更快?

c# - Entity Framework : storing as a list of complex type

NHibernate 多对多效率低下?

NHibernate 3.3 和 SysCache

nhibernate L2缓存: configure by code

确定缓存级别和大小的 C 程序

ruby-on-rails - Google Geocoding API 错误 : over query limit. - Rails

sql - 在自连接字段上执行递归 SQL 查询的最佳方法是什么(以及通过 nhibernate 执行此操作?)