从数据库中删除对象时如何从缓存中删除对象?

时间:2012-10-03 23:39:20

标签: nhibernate sqldependency syscache2

在过去的几个月里,我一直在努力在我们的一个ASP.NET MVC(Web API)Web服务项目中实现NHibernate。我正在使用NHibernate 3.3.1,并且我已经针对该版本的NHibernate下载并编译了SysCache2,因为它听起来像是我们需要的最佳匹配。我们这个Web服务的目标是让它为多个其他Web应用程序提供员工数据,从而允许我们将这些信息缓存在一个中心位置,并减少对员工数据库的冗余查询拦截。

我偶然发现了它,并使SqlDependency工作得相当好。当我对记录进行更改时,我在NHibernate日志中看到了一个DependencyChanged事件,并从数据库中获取了一个新的副本。当我删除数据库中的一行时出现问题:SqlDependency似乎没有将此信息传达给SysCache2,因为如果我尝试运行将返回已删除记录的查询(如果它没有被删除),我会得到典型的来自NHibernate的“不存在具有给定标识符的行”。这就像NHibernate没有意识到该行已被删除。

我为添加到缓存表的新行获得了类似的行为。新行没有出现在常规轮询间隔(5秒),通常需要几分钟(我还没弄清楚是什么原因导致它在几分钟后突然出现)。

我想我可能错过了我的配置中的一个步骤,因为我已经从大约200个不同的线程拼凑起来,人们已经在谈论他们的SysCache& SqlDependency配置。我确定我丢失了一些块,可能还有一些不必要的块。如果有任何关于设置SysCache2和/或SqlDependency的全面参考,我当然没有找到它,并且可以在那里使用一些指针。我有很多关于配置的问题(例如我应该如何设置我的缓存区域,因为我目前在数据库中的每个表都有一个区域似乎很傻),但是现在最紧迫的问题是“没有行给定的标识符“exception。

这是我完整的NHibernate配置(流畅):

var config = Fluently.Configure()
    .Database(MsSqlConfiguration.MsSql2008
        //.ShowSql()
        .ConnectionString(s => s.FromConnectionStringWithKey("HumanResourceConnection"))
        .DefaultSchema("dbo"))
    .Cache(c => c
        .UseSecondLevelCache()
        .UseQueryCache()
        .ProviderClass<SysCacheProvider>())
    .Mappings(m =>
        m.AutoMappings.Add(AutoMap.AssemblyOf<Employee>(new AutomappingConfiguration()).Conventions
            .AddFromAssemblyOf<DataAccessPropertyConvention>()
            .UseOverridesFromAssemblyOf<LocationMappingOverride>()))
    .ExposeConfiguration(c =>
        c.LinqToHqlGeneratorsRegistry<DataAccessLinqToHqlGeneratorsRegistry>())
    .ExposeConfiguration(c =>
        c.AppendListeners(
            ListenerType.PreUpdate,
            new IPreUpdateEventListener[] { new AuditEventListener() }))
    .ExposeConfiguration(c =>
        c.AppendListeners(
            ListenerType.PreInsert, new IPreInsertEventListener[] { new AuditEventListener() }));

这是我们上面引用的DataAccessClassConvention类,它可能是您可能需要查看的唯一类。这将查看正在创建的每个映射,查找我们创建的属性以定义实例应映射到的缓存区域,并设置该属性。它还可以在具有该自定义属性的任何实例上启用缓存。模式行用于不在连接字符串指向的数据库中的对象。

/// <summary>
/// Default Class Convention for all dataobjects
/// </summary>
public class DataAccessClassConvention : IClassConvention
{
    public void Apply(IClassInstance instance)
    {        
        // Maps last element of namespace to database name
        instance.Schema(instance.EntityType.Namespace.Substring(instance.EntityType.Namespace.LastIndexOf('.') + 1) + ".dbo");

        // Enable second-level caching if a cache region is specified.
        var attributeArray = (CacheRegionAttribute[]) instance.EntityType.GetCustomAttributes(typeof(CacheRegionAttribute), false);
        if (attributeArray.Length > 0)
        {
            // Enable caching.
            instance.Cache.ReadWrite();

            // Set cache region for SqlDependency.
            var attribute = attributeArray.First();
            instance.Cache.Region(attribute.CacheRegion);
        }
    }
}

以下是我的web.config中的SqlDependency部分:

<sqlCacheDependency enabled="true" pollTime="5000">
  <databases>
    <add name="HumanResource" connectionStringName="HumanResourceConnection" />
  </databases>
</sqlCacheDependency>

以下是我的一个缓存区域的示例,它们几乎完全相同:

<cacheRegion name="EmployeeRegion" relativeExpiration="86400">
  <dependencies>
    <commands>
      <add name="Employee" command="SELECT employee_id from dbo.Employee" />
    </commands>
  </dependencies>
</cacheRegion>

我错过了什么?

0 个答案:

没有答案