2010-11-11 93 views
5

问题

我们有一个复杂的域模型。为了避免性能问题,大多数列表(由域对象生成)被缓存。一切正常,直到第一个域对象改变。必须刷新缓存中的所有依赖列表 - 问题是:如何?域对象更改 - 需要缓存列表刷新

  • Domain对象:房子
  • 行动:房子的名称已更改
  • 影响:所有的列表(containts房子的名字)是失日期,需要更新

解决方案

毫无疑问,有一个非常简单的方法:在保存一个域对象后,我们手动刷新代码中的所有列表。

伪代码

repository.Save(save); 

cacheManager.Invalidate("HouseList"); 
cacheManager.Invalidate("OrderedHouseList"); 
cacheManager.Invalidate("HousecombinedWithResidentsList"); 
... 

所以问题是:我们要刷新一切手动。我在寻找更好的解决方案,让我们说:

  • 面向方面的方式W/PostSharp或温莎
  • 观察员或基于事件的技术
  • CQRS它是关于分离查询和命令,但这种观念也许是太许多。

任何想法或经验?

回答

1

此问题的答案很复杂,因为您的要求不明确。数据可以陈旧吗?如果是这样,多久?

根据您发布的信息有限,我建议“缓存”的视图仅仅是对真实数据的查询。查询本身可以周期性地刷新其缓存结果。

+0

良好的后续问题。 – 2010-11-12 20:26:26

+0

“数据可能陈旧吗?如果是这样,多长时间?”:大概1小时,也许1年。主要问题来自不稳定的业务领域。 – boj 2010-11-12 20:28:27

0

我想说,如果您的插入/更新/删除修改其中一个列表的内容,您应该重新查询列表。我的应用程序中有一些缓存的数据表,我使用下面的结构集合来维护它们。这样,很容易清除整个缓存,并且当我询问特定的数据表时,我会检查缓存中是否存在未过期的数据。

Protected Structure CachedDT 

    #Region "Local Variables" 

    Public TheDT As DataTable 
    Public TheExpirationTime As DateTime 
    Public TheUniqueIdentifier As String 

    #End Region 'Local Variables 

End Structure 

Protected cCachedDTs As Dictionary(Of String, CachedDT) = New Dictionary(Of String, CachedDT) 

这些生活在我的基类中查询数据库的对象。使用高速缓存的数据表的一个例子是:

<System.Diagnostics.DebuggerStepThrough> _ 
    Public Overrides Function GetPermissionsSystem(ByVal SystemUserName As String) As DataTable 
     Try 
      Dim oCmd As New SqlCommand 
      Dim aDpt As New SqlDataAdapter 
      Dim aDst As New DataSet 
      Dim theCached As CachedDT 
      Dim theCacheName As String = "GetPermissionsSystem|" & SystemUserName 
      If cCachedDTs.ContainsKey(theCacheName) Then 
       theCached = cCachedDTs.Item(theCacheName) 
       If theCached.TheExpirationTime < DateTime.Now Then 
        cCachedDTs.Remove(theCacheName) 
       Else 
        Return theCached.TheDT 
       End If 
      End If 
      With oCmd 
       .Connection = MyBase.Conn 
       .CommandType = CommandType.StoredProcedure 
       .CommandTimeout = MyBase.TimeoutShort 
       .CommandText = Invoicing.GetPermissionsSystem 
       .Parameters.Add(GP("@SystemUserName", SystemUserName)) 
      End With 
      aDpt.SelectCommand = oCmd 
      aDpt.Fill(aDst) 
      theCached = New CachedDT 
      With theCached 
       .TheUniqueIdentifier = theCacheName 
       .TheExpirationTime = DateTime.Now.AddSeconds(10) 
       .TheDT = aDst.Tables(0) 
      End With 
      cCachedDTs.Add(theCached.TheUniqueIdentifier, theCached) 
      Return aDst.Tables(0) 
     Catch sqlex As SqlException 
      MyBase.HandelEX(sqlex) 
     Catch ex As Exception 
      MyBase.HandleEX(ex) 
     Finally 
      MyBase.CloseConn() 
     End Try 
    End Function 

在上面的例子中,功能检查高速缓存看到一个合适的对象是否存在。如果确实如此,则返回而不是再次访问数据库。最后,新的对象被添加到缓存中。

你所要做的只是提供一些从缓存中删除特定列表的方法。然后,当你做一个插入/更新/删除,确保你清除适当的项目。

+0

对不起,代码在VB中,而不是C#。 http://www.developerfusion.com/tools/convert/csharp-to-vb/会为你转换它,如果它是一个合适的探测解决方案。 – 2010-11-12 16:12:43

+0

谢谢,但这只是关于缓存(我更喜欢EntLib缓存应用程序块),而不是复杂的缓存刷新。 – boj 2010-11-12 20:09:04