Session 在支持二级缓存/事务等的asp.net-mvc中执行nhibernate会话管理的推荐方法是什么?

Session 在支持二级缓存/事务等的asp.net-mvc中执行nhibernate会话管理的推荐方法是什么?,session,nhibernate,transactions,second-level-cache,Session,Nhibernate,Transactions,Second Level Cache,我正在努力让二级缓存和事务在我的asp.net-mvc站点中工作,我认为这与我如何设置会话管理有关 基本上我有以下课程: NhibernateRepository 会话管理器 我正在使用Unity IOC容器: this.RegisterType<IRepository, NHibernateRepository>(new PerResolveLifetimeManager()); this.RegisterType<ISessionManager, SessionMana

我正在努力让二级缓存和事务在我的asp.net-mvc站点中工作,我认为这与我如何设置会话管理有关

基本上我有以下课程:

  • NhibernateRepository
  • 会话管理器
我正在使用Unity IOC容器:

this.RegisterType<IRepository, NHibernateRepository>(new PerResolveLifetimeManager());
this.RegisterType<ISessionManager, SessionManager>(new PerResolveLifetimeManager());
会话管理器类如下所示:

public class SessionManager : ISessionManager
{
    private static readonly ResourceLock _lock = new OneManyResourceLock();

    public static ISessionFactory Factory { get; set; }


    public ISession GetSession(string userName)
    {
        ISession session = GetSessionFactory().OpenSession(new AuditInterceptor(userName));
        return session;
    }

    private static ISessionFactory GetSessionFactory()
    {
        using (_lock.WaitToRead())
        {
            if (Factory != null) return Factory;
        }
        using (_lock.WaitToWrite())
        {
            if (Factory != null) return Factory;
            string connectionString = ConfigurationManager.ConnectionStrings["DomainConnection"].ConnectionString;
            Factory = FluentlyConfigureFactory(connectionString, false);
            return Factory;
        }
    }

    private static ISessionFactory FluentlyConfigureFactory(string connectionString, bool showSql)
    {
          MsSqlConfiguration databaseConfiguration = MsSqlConfiguration.MsSql2005
            .ConnectionString(c => c.Is(connectionString))
            .Dialect<SparcMsSqlDialect>()
            .UseOuterJoin()
            .UseReflectionOptimizer();

        if (showSql)
        {
            databaseConfiguration.ShowSql();                
        }

        databaseConfiguration.Raw("generate_statistics", showSql.ToString());

        FluentConfiguration configuration = Fluently.Configure().Database(databaseConfiguration);
       return configuration
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ApplicationMap>().Conventions.Add(typeof(Conventions)))
            .ExposeConfiguration(
                c => {
                    c.SetProperty("cache.provider_class", "NHibernate.Caches.SysCache.SysCacheProvider, NHibernate.Caches.SysCache");
                    c.SetProperty("cache.use_second_level_cache", "true");
                    c.SetProperty("cache.use_query_cache", "true");
                    c.SetProperty("expiration", "86400");
                })
            .BuildSessionFactory();
    }

所以我恢复了那个密码。基本上,我希望在asp.net-mvc中使用任何第二级缓存、事务时都有一个“转到”最佳实践

我喜欢使用一个实际上可以为您处理对象锁的实现,我已经为nHibernate的2级缓存实现了一个自定义模块,您可以通过进行一些小配置来插入,因为您需要实现is ICache接口

 public class NHibernateCache2 : ICache
    {
        private static readonly IInternalLogger Log = LoggerProvider.LoggerFor(typeof(NHibernateCache2));
        private readonly string _region;
        private string _regionPrefix;
        private readonly MemoryCache _cache;
        private TimeSpan _expiration;
        private CacheItemPriority _priority;
        // The name of the cache key used to clear the cache. All cached items depend on this key.
        private readonly string _rootCacheKey;
        private bool _rootCacheKeyStored;
        private static readonly TimeSpan DefaultExpiration = TimeSpan.FromSeconds(300);
        private static readonly string DefauktRegionPrefix = string.Empty;
        private const string CacheKeyPrefix = "NHibernate-Cache:";

        public NHibernateCache2():this("nhibernate", null)
        {
        }

        public NHibernateCache2(string region):this(region, null)
        {
        }

        /// There are two (2) configurable parameters:
        /// expiration = number of seconds to wait before expiring each item
        /// priority = a numeric cost of expiring each item, where 1 is a low cost, 5 is the highest, and 3 is normal. Only values 1 through 5 are valid.
        /// All parameters are optional. The defaults are an expiration of 300 seconds and the default priority of 3.

        public NHibernateCache2(string region, IDictionary<string, string> properties)
        {
            _region = region;
            _cache = MemoryCache.Default;
            Configure(properties);
            _rootCacheKey = GenerateRootCacheKey();
            StoreRootCacheKey();
        }

        /// Defines property in order to get the region for the NHibernate's Cache.
        public string Region
        {
            get { return _region; }
        }

        /// Obtains a expiration value that indicates the time in seconds after which an object is automatically 
        /// evicted from the cache.
        public TimeSpan Expiration
        {
            get { return _expiration; }
        }

        /// Obtains a priority value that indicates the likelihood that an object of that region evicts 
        /// another already cached object of a lower priority region.
        public CacheItemPriority Priority
        {
            get { return _priority; }
        }

        private void Configure(IDictionary<string, string> props)
        {
            if (props == null)
            {
                if (Log.IsWarnEnabled)
                {
                    Log.Warn("configuring cache with default values");
                }
                _expiration = DefaultExpiration;
                _priority = CacheItemPriority.Default;
                _regionPrefix = DefauktRegionPrefix;
            }
            else
            {
                _priority = GetPriority(props);
                _expiration = GetExpiration(props);
                _regionPrefix = GetRegionPrefix(props);
            }
        }

        private static string GetRegionPrefix(IDictionary<string, string> props)
        {
            string result;
            if (props.TryGetValue("regionPrefix", out result))
            {
                Log.DebugFormat("new regionPrefix :{0}", result);
            }
            else
            {
                result = DefauktRegionPrefix;
                Log.Debug("no regionPrefix value given, using defaults");
            }
            return result;
        }

        private static TimeSpan GetExpiration(IDictionary<string, string> props)
        {
            TimeSpan result = DefaultExpiration;
            string expirationString;
            if (!props.TryGetValue("expiration", out expirationString))
            {
                props.TryGetValue(NHibernate.Cfg.Environment.CacheDefaultExpiration, out expirationString);
            }

            if (expirationString != null)
            {
                try
                {
                    int seconds = Convert.ToInt32(expirationString);
                    result = TimeSpan.FromSeconds(seconds);
                    Log.Debug("new expiration value: " + seconds);
                }
                catch (Exception ex)
                {
                    Log.Error("error parsing expiration value");
                    throw new ArgumentException("could not parse 'expiration' as a number of seconds", ex);
                }
            }
            else
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("no expiration value given, using defaults");
                }
            }
            return result;
        }

        private static CacheItemPriority GetPriority(IDictionary<string, string> props)
        {
            CacheItemPriority result = CacheItemPriority.Default;
            string priorityString;
            if (props.TryGetValue("priority", out priorityString))
            {
                result = ConvertCacheItemPriorityFromXmlString(priorityString);
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("new priority: " + result);
                }
            }
            return result;
        }


        private static CacheItemPriority ConvertCacheItemPriorityFromXmlString(string priorityString)
        {
            if (string.IsNullOrEmpty(priorityString))
            {
                return CacheItemPriority.Default;
            }
            var ps = priorityString.Trim().ToLowerInvariant();
            if (ps.Length == 1 && char.IsDigit(priorityString, 0))
            {
                // the priority is specified as a number
                int priorityAsInt = int.Parse(ps);
                if (priorityAsInt >= 1 && priorityAsInt <= 6)
                {
                    return (CacheItemPriority)priorityAsInt;
                }
            }
            else
            {
                /// change for your own priority settings
                switch (ps)
                {
                    case "abovenormal":
                        return CacheItemPriority.Default;
                    case "belownormal":
                        return CacheItemPriority.Default;
                    case "default":
                        return CacheItemPriority.Default;
                    case "high":
                        return CacheItemPriority.Default;
                    case "low":
                        return CacheItemPriority.Default;
                    case "normal":
                        return CacheItemPriority.Default;
                    case "notremovable":
                        return CacheItemPriority.NotRemovable;
                }
            }
            Log.Error("priority value out of range: " + priorityString);
            throw new IndexOutOfRangeException("Priority must be a valid System.Web.Caching.CacheItemPriority; was: " + priorityString);
        }

        private string GetCacheKey(object key)
        {
            return String.Concat(CacheKeyPrefix, _regionPrefix, _region, ":", key.ToString(), "@", key.GetHashCode());
        }

        /// Gets an object that exist in the second level cache of NHibernate by the specified key.
        ///A unique identifier for the cache entry to get.
        ///Returns an entry from the NHibernate's Cache.
        public object Get(object key)
        {
            if (key == null)
            {
                return null;
            }
            string cacheKey = GetCacheKey(key);
            if (Log.IsDebugEnabled)
            {
                Log.Debug(String.Format("Fetching object '{0}' from the cache.", cacheKey));
            }

            object obj = _cache.Get(cacheKey);
            if (obj == null)
            {
                return null;
            }

            var de = (DictionaryEntry)obj;
            if (key.Equals(de.Key))
            {
                return de.Value;
            }
            else
            {
                return null;
            }
        }

        /// Adds a specific object inside the in the second level cache of NHibernate by using its key and its content.
        /// A key value of an item from the second level cache of NHibernate.
        /// Data for an entry of second level cache of NHibernate.
        public void Put(object key, object value)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key", "null key not allowed");
            }
            if (value == null)
            {
                throw new ArgumentNullException("value", "null value not allowed");
            }
            string cacheKey = GetCacheKey(key);
            if (_cache[cacheKey] != null)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(String.Format("updating value of key '{0}' to '{1}'.", cacheKey, value));
                }

                // Remove the key to re-add it again below
                _cache.Remove(cacheKey);
            }
            else
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(String.Format("adding new data: key={0}&value={1}", cacheKey, value));
                }
            }

            if (!_rootCacheKeyStored)
            {
                StoreRootCacheKey();
            }

            var cacheItemPolicy = new CacheItemPolicy()
            {
                AbsoluteExpiration = DateTime.Now.Add(_expiration),
                SlidingExpiration = ObjectCache.NoSlidingExpiration,
                Priority = _priority,
            };
            cacheItemPolicy.ChangeMonitors.Add(_cache.CreateCacheEntryChangeMonitor(new[] { _rootCacheKey }));
            _cache.Add(
                cacheKey,
                new DictionaryEntry(key, value),
                cacheItemPolicy);
        }

        /// Removes a cache entry from second level cache of NHibernate by a key. 
        /// A key value of an item from second level cache of NHibernate.
        public void Remove(object key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            string cacheKey = GetCacheKey(key);
            if (Log.IsDebugEnabled)
            {
                Log.Debug("removing item with key: " + cacheKey);
            }
            _cache.Remove(cacheKey);
        }

        /// Removes an object/item from second level cache of NHibernate.
        public void Clear()
        {
            RemoveRootCacheKey();
            StoreRootCacheKey();
        }

        /// Generate a unique root key for all cache items to be dependant upon
        private string GenerateRootCacheKey()
        {
            return GetCacheKey(Guid.NewGuid());
        }

        private void RootCacheItemRemoved(CacheEntryRemovedArguments arguments)
        {
            _rootCacheKeyStored = false;
        }

        private void StoreRootCacheKey()
        {
            _rootCacheKeyStored = true;
            var policy = new CacheItemPolicy
            {
                AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
                SlidingExpiration = ObjectCache.NoSlidingExpiration,
                Priority = CacheItemPriority.Default,
                RemovedCallback = RootCacheItemRemoved
            };
            _cache.Add(
                _rootCacheKey,
                _rootCacheKey,
                policy);
        }

        private void RemoveRootCacheKey()
        {
            _cache.Remove(_rootCacheKey);
        }

        /// Clears the second level cache of NHibernate.
        public void Destroy()
        {
            Clear();
        }

        public void Lock(object key)
        {
            // Do nothing
        }

        public void Unlock(object key)
        {
            // Do nothing
        }
        /// Obtains the next timestamp value.
        public long NextTimestamp()
        {
            return Timestamper.Next();
        }

        /// Defines property in order to get the sliding expiration time for the second level cache of NHibernate.
        public int Timeout
        {
            get { return Timestamper.OneMs * 60000; } // 60 seconds
        }

        /// Retrieves the name of NHibernate second level cache region.
        public string RegionName
        {
            get { return _region; }
        }
    }
公共类NHibernateCache2:ICache
{
private static readonly IInternalLogger Log=LoggerProvider.LoggerFor(typeof(NHibernateCache2));
私有只读字符串\u区域;
私有字符串_regionPrefix;
私有只读存储器缓存;
私人时间跨度\u到期;
私有缓存项优先级_优先级;
//用于清除缓存的缓存键的名称。所有缓存项都依赖于此键。
私有只读字符串_rootCacheKey;
私人住宅区;
私有静态只读TimeSpan DefaultExpiration=TimeSpan.FromSeconds(300);
私有静态只读字符串DefauktRegionPrefix=string.Empty;
private const string CacheKeyPrefix=“NHibernate Cache:”;
public NHibernateCache2():此(“nhibernate”,null)
{
}
公共NHibernateCache2(字符串区域):此(区域,null)
{
}
///有两(2)个可配置参数:
///expiration=每个项目过期前等待的秒数
///优先级=使每个项目过期的数字成本,其中1是低成本,5是最高成本,3是正常成本。只有值1到5有效。
///所有参数都是可选的。默认值为过期300秒,默认优先级为3。
公共NHibernateCache2(字符串区域,IDictionary属性)
{
_区域=区域;
_cache=MemoryCache.Default;
配置(属性);
_rootCacheKey=GenerateRootCacheKey();
StoreRootCacheKey();
}
///定义属性以获取NHibernate缓存的区域。
公共字符串区域
{
获取{return\u region;}
}
///获取一个过期值,该值指示在该时间之后自动创建对象的时间(以秒为单位)
///从缓存中逐出。
公共时间跨度到期
{
获取{return\u expiration;}
}
///获取一个优先级值,该值指示该区域的对象退出的可能性
///另一个已缓存的低优先级区域的对象。
公共缓存项优先级
{
获取{return\u priority;}
}
私有void配置(IDictionary道具)
{
if(props==null)
{
如果(Log.iswarn已启用)
{
Log.Warn(“使用默认值配置缓存”);
}
_到期=默认到期;
_优先级=CacheItemPriority.Default;
_regionPrefix=DefauktRegionPrefix;
}
其他的
{
_优先级=获取优先级(道具);
_到期=获取到期(道具);
_regionPrefix=GetRegionPrefix(道具);
}
}
私有静态字符串GetRegionPrefix(IDictionary道具)
{
字符串结果;
if(props.TryGetValue(“regionPrefix”,输出结果))
{
DebugFormat(“新区域前缀:{0}”,结果);
}
其他的
{
结果=DefauktRegionPrefix;
Debug(“没有给定regionPrefix值,使用默认值”);
}
返回结果;
}
私有静态TimeSpan GetExpiration(IDictionary道具)
{
TimeSpan结果=DefaultExpiration;
字符串过期字符串;
如果(!props.TryGetValue(“到期”,out expirationString))
{
props.TryGetValue(NHibernate.Cfg.Environment.CacheDefaultExpiration,out expirationString);
}
if(expirationString!=null)
{
尝试
{
int seconds=Convert.ToInt32(expirationString);
结果=从秒开始的时间跨度(秒);
Log.Debug(“新过期值:“+秒”);
}
捕获(例外情况除外)
{
Log.Error(“解析过期值时出错”);
抛出新的ArgumentException(“无法将'expiration'解析为秒数”,例如);
}
}
其他的
{
if(Log.IsDebugEnabled)
{
Debug(“没有给出过期值,使用默认值”);
}
}
返回结果;
}
私有静态CacheItemPriority GetPriority(IDictionary道具)
{
CacheItemPriority结果=CacheItemPriority.Default;
字符串优先级字符串;
if(props.TryGetValue(“优先级”,out priorityString))
{
结果=ConvertCacheItemPriorityFromXmlString(priorityString);
if(Log.IsDebugEnabled)
{
Log.Debug(“新优先级:+结果”);
    Initializing[ (one of my domain objects) #1]-Could not initialize proxy - no Session. 
 public class NHibernateCache2 : ICache
    {
        private static readonly IInternalLogger Log = LoggerProvider.LoggerFor(typeof(NHibernateCache2));
        private readonly string _region;
        private string _regionPrefix;
        private readonly MemoryCache _cache;
        private TimeSpan _expiration;
        private CacheItemPriority _priority;
        // The name of the cache key used to clear the cache. All cached items depend on this key.
        private readonly string _rootCacheKey;
        private bool _rootCacheKeyStored;
        private static readonly TimeSpan DefaultExpiration = TimeSpan.FromSeconds(300);
        private static readonly string DefauktRegionPrefix = string.Empty;
        private const string CacheKeyPrefix = "NHibernate-Cache:";

        public NHibernateCache2():this("nhibernate", null)
        {
        }

        public NHibernateCache2(string region):this(region, null)
        {
        }

        /// There are two (2) configurable parameters:
        /// expiration = number of seconds to wait before expiring each item
        /// priority = a numeric cost of expiring each item, where 1 is a low cost, 5 is the highest, and 3 is normal. Only values 1 through 5 are valid.
        /// All parameters are optional. The defaults are an expiration of 300 seconds and the default priority of 3.

        public NHibernateCache2(string region, IDictionary<string, string> properties)
        {
            _region = region;
            _cache = MemoryCache.Default;
            Configure(properties);
            _rootCacheKey = GenerateRootCacheKey();
            StoreRootCacheKey();
        }

        /// Defines property in order to get the region for the NHibernate's Cache.
        public string Region
        {
            get { return _region; }
        }

        /// Obtains a expiration value that indicates the time in seconds after which an object is automatically 
        /// evicted from the cache.
        public TimeSpan Expiration
        {
            get { return _expiration; }
        }

        /// Obtains a priority value that indicates the likelihood that an object of that region evicts 
        /// another already cached object of a lower priority region.
        public CacheItemPriority Priority
        {
            get { return _priority; }
        }

        private void Configure(IDictionary<string, string> props)
        {
            if (props == null)
            {
                if (Log.IsWarnEnabled)
                {
                    Log.Warn("configuring cache with default values");
                }
                _expiration = DefaultExpiration;
                _priority = CacheItemPriority.Default;
                _regionPrefix = DefauktRegionPrefix;
            }
            else
            {
                _priority = GetPriority(props);
                _expiration = GetExpiration(props);
                _regionPrefix = GetRegionPrefix(props);
            }
        }

        private static string GetRegionPrefix(IDictionary<string, string> props)
        {
            string result;
            if (props.TryGetValue("regionPrefix", out result))
            {
                Log.DebugFormat("new regionPrefix :{0}", result);
            }
            else
            {
                result = DefauktRegionPrefix;
                Log.Debug("no regionPrefix value given, using defaults");
            }
            return result;
        }

        private static TimeSpan GetExpiration(IDictionary<string, string> props)
        {
            TimeSpan result = DefaultExpiration;
            string expirationString;
            if (!props.TryGetValue("expiration", out expirationString))
            {
                props.TryGetValue(NHibernate.Cfg.Environment.CacheDefaultExpiration, out expirationString);
            }

            if (expirationString != null)
            {
                try
                {
                    int seconds = Convert.ToInt32(expirationString);
                    result = TimeSpan.FromSeconds(seconds);
                    Log.Debug("new expiration value: " + seconds);
                }
                catch (Exception ex)
                {
                    Log.Error("error parsing expiration value");
                    throw new ArgumentException("could not parse 'expiration' as a number of seconds", ex);
                }
            }
            else
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("no expiration value given, using defaults");
                }
            }
            return result;
        }

        private static CacheItemPriority GetPriority(IDictionary<string, string> props)
        {
            CacheItemPriority result = CacheItemPriority.Default;
            string priorityString;
            if (props.TryGetValue("priority", out priorityString))
            {
                result = ConvertCacheItemPriorityFromXmlString(priorityString);
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("new priority: " + result);
                }
            }
            return result;
        }


        private static CacheItemPriority ConvertCacheItemPriorityFromXmlString(string priorityString)
        {
            if (string.IsNullOrEmpty(priorityString))
            {
                return CacheItemPriority.Default;
            }
            var ps = priorityString.Trim().ToLowerInvariant();
            if (ps.Length == 1 && char.IsDigit(priorityString, 0))
            {
                // the priority is specified as a number
                int priorityAsInt = int.Parse(ps);
                if (priorityAsInt >= 1 && priorityAsInt <= 6)
                {
                    return (CacheItemPriority)priorityAsInt;
                }
            }
            else
            {
                /// change for your own priority settings
                switch (ps)
                {
                    case "abovenormal":
                        return CacheItemPriority.Default;
                    case "belownormal":
                        return CacheItemPriority.Default;
                    case "default":
                        return CacheItemPriority.Default;
                    case "high":
                        return CacheItemPriority.Default;
                    case "low":
                        return CacheItemPriority.Default;
                    case "normal":
                        return CacheItemPriority.Default;
                    case "notremovable":
                        return CacheItemPriority.NotRemovable;
                }
            }
            Log.Error("priority value out of range: " + priorityString);
            throw new IndexOutOfRangeException("Priority must be a valid System.Web.Caching.CacheItemPriority; was: " + priorityString);
        }

        private string GetCacheKey(object key)
        {
            return String.Concat(CacheKeyPrefix, _regionPrefix, _region, ":", key.ToString(), "@", key.GetHashCode());
        }

        /// Gets an object that exist in the second level cache of NHibernate by the specified key.
        ///A unique identifier for the cache entry to get.
        ///Returns an entry from the NHibernate's Cache.
        public object Get(object key)
        {
            if (key == null)
            {
                return null;
            }
            string cacheKey = GetCacheKey(key);
            if (Log.IsDebugEnabled)
            {
                Log.Debug(String.Format("Fetching object '{0}' from the cache.", cacheKey));
            }

            object obj = _cache.Get(cacheKey);
            if (obj == null)
            {
                return null;
            }

            var de = (DictionaryEntry)obj;
            if (key.Equals(de.Key))
            {
                return de.Value;
            }
            else
            {
                return null;
            }
        }

        /// Adds a specific object inside the in the second level cache of NHibernate by using its key and its content.
        /// A key value of an item from the second level cache of NHibernate.
        /// Data for an entry of second level cache of NHibernate.
        public void Put(object key, object value)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key", "null key not allowed");
            }
            if (value == null)
            {
                throw new ArgumentNullException("value", "null value not allowed");
            }
            string cacheKey = GetCacheKey(key);
            if (_cache[cacheKey] != null)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(String.Format("updating value of key '{0}' to '{1}'.", cacheKey, value));
                }

                // Remove the key to re-add it again below
                _cache.Remove(cacheKey);
            }
            else
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug(String.Format("adding new data: key={0}&value={1}", cacheKey, value));
                }
            }

            if (!_rootCacheKeyStored)
            {
                StoreRootCacheKey();
            }

            var cacheItemPolicy = new CacheItemPolicy()
            {
                AbsoluteExpiration = DateTime.Now.Add(_expiration),
                SlidingExpiration = ObjectCache.NoSlidingExpiration,
                Priority = _priority,
            };
            cacheItemPolicy.ChangeMonitors.Add(_cache.CreateCacheEntryChangeMonitor(new[] { _rootCacheKey }));
            _cache.Add(
                cacheKey,
                new DictionaryEntry(key, value),
                cacheItemPolicy);
        }

        /// Removes a cache entry from second level cache of NHibernate by a key. 
        /// A key value of an item from second level cache of NHibernate.
        public void Remove(object key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            string cacheKey = GetCacheKey(key);
            if (Log.IsDebugEnabled)
            {
                Log.Debug("removing item with key: " + cacheKey);
            }
            _cache.Remove(cacheKey);
        }

        /// Removes an object/item from second level cache of NHibernate.
        public void Clear()
        {
            RemoveRootCacheKey();
            StoreRootCacheKey();
        }

        /// Generate a unique root key for all cache items to be dependant upon
        private string GenerateRootCacheKey()
        {
            return GetCacheKey(Guid.NewGuid());
        }

        private void RootCacheItemRemoved(CacheEntryRemovedArguments arguments)
        {
            _rootCacheKeyStored = false;
        }

        private void StoreRootCacheKey()
        {
            _rootCacheKeyStored = true;
            var policy = new CacheItemPolicy
            {
                AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
                SlidingExpiration = ObjectCache.NoSlidingExpiration,
                Priority = CacheItemPriority.Default,
                RemovedCallback = RootCacheItemRemoved
            };
            _cache.Add(
                _rootCacheKey,
                _rootCacheKey,
                policy);
        }

        private void RemoveRootCacheKey()
        {
            _cache.Remove(_rootCacheKey);
        }

        /// Clears the second level cache of NHibernate.
        public void Destroy()
        {
            Clear();
        }

        public void Lock(object key)
        {
            // Do nothing
        }

        public void Unlock(object key)
        {
            // Do nothing
        }
        /// Obtains the next timestamp value.
        public long NextTimestamp()
        {
            return Timestamper.Next();
        }

        /// Defines property in order to get the sliding expiration time for the second level cache of NHibernate.
        public int Timeout
        {
            get { return Timestamper.OneMs * 60000; } // 60 seconds
        }

        /// Retrieves the name of NHibernate second level cache region.
        public string RegionName
        {
            get { return _region; }
        }
    }
public class NHibernateCacheProvider2 : ICacheProvider
    {
        private static readonly Dictionary<string, ICache> Caches;
        private static readonly IInternalLogger Log;

        static NHibernateCacheProvider2()
        {
            Log = LoggerProvider.LoggerFor(typeof(NHibernateCacheProvider2));
            Caches = new Dictionary<string, ICache>();
        }

        /// Builds a new SysCache through the region and a collection of properties.
        /// regionName: The name of the cache region.
        /// properties: Configuration settings.
        /// returns A new instance of NHibernateCache by using a region of the cache.
        public ICache BuildCache(string regionName, IDictionary<string, string> properties)
        {
            if (regionName == null)
            {
                regionName = string.Empty;
            }

            ICache result;
            if (Caches.TryGetValue(regionName, out result))
            {
                return result;
            }

            // create cache
            if (properties == null)
            {
                properties = new Dictionary<string, string>(1);
            }

            if (Log.IsDebugEnabled)
            {
                var sb = new StringBuilder();
                sb.Append("building cache with region: ").Append(regionName).Append(", properties: ");

                foreach (KeyValuePair<string, string> de in properties)
                {
                    sb.Append("name=");
                    sb.Append(de.Key);
                    sb.Append("&value=");
                    sb.Append(de.Value);
                    sb.Append(";");
                }
                Log.Debug(sb.ToString());
            }
            return new NHibernateCache2(regionName, properties);
        }

        public long NextTimestamp()
        {
            return Timestamper.Next();
        }


        public void Start(IDictionary<string, string> properties) { //your impl it's not necessary }

        public void Stop() { }

    }
Fluently.Configure().Database(MsSqlConfiguration.MsSql2008.
ConnectionString(builder =>   builder.FromConnectionStringWithKey(connectionStringKey)))
.ExposeConfiguration(c =>{c.SetProperty("show_sql", "true");}).
Cache(builder =>builder.ProviderClass<NHibernateCacheProvider2().
UseSecondLevelCache().UseQueryCache())