65.9K
CodeProject 正在变化。 阅读更多。
Home

强制 XmlDataSource 缓存失效的技巧

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.17/5 (4投票s)

2008 年 6 月 16 日

CPOL

2分钟阅读

viewsIcon

38752

downloadIcon

132

我发现当你通过代码更改 XmlDataSource 控件的 Data 属性时,它不会自动使缓存失效。 这是一个针对此问题的 hack。

引言

我们经常将 XmlDataSource 控件与 TreeView 控件一起使用。

如果数据源是静态的,它工作得很好。但是,当数据源需要是动态的时,似乎存在一些问题。本文将介绍其中一个问题,并为您提供一个 hack 解决方案。

症状

如果数据源需要是动态的,您可以选择

  1. 在 Web 表单上放置多个 XmlDataSource 控件,并通过设置不同的 DataSourceID 来切换它们。
  2. 仅放置一个 XmlDataSource 控件,并在必要时更改其 DataFileData 属性的值。

显然,第一种方式更受限制,仅适用于某些特殊情况。在表单上放置大量数据源控件不是一个好主意,更重要的是,数据源控件的数量必须是一个固定值。

但是,当您更改 XmlDataSource 控件的 DataFileData 属性的值时会发生什么? 从 Microsoft 的文档中,您可能会发现以下信息

如果您更改 DataFile/Data 属性的值,则会引发 DataSourceChanged 事件。 如果启用了缓存并且您更改了 DataFile/Data 的值,则会使缓存失效。

不幸的是,在我的测试中(您可以下载示例自己查看),我发现当您更改 XmlDataSource 控件的 Data 属性的值时,缓存 不会 自动失效,尽管 DataFile 没有问题。

解决方法

首先,您可以选择更改 XmlDataSourceDataFile 属性的值,而不是 Data。 这是一个简单的解决方案。

否则,如果您出于某种原因坚持更改 Data 的属性(例如,您的数据源不是真正的 XML 文件,而只是一个动态填充的字符串),您可以尝试以下 hack 方法

public static void XmlDataSourceCacheHack(XmlDataSource dataSource)
{
    try
    {
        Type t = typeof(XmlDataSource);
        MethodInfo m = t.GetMethod("CreateCacheKey", 
                       BindingFlags.Instance | BindingFlags.NonPublic);
        string key = (string)m.Invoke(dataSource, null);
        PropertyInfo p = t.GetProperty("Cache", 
                         BindingFlags.Instance | BindingFlags.NonPublic);
        object cache = p.GetValue(dataSource, null);

        Type t2 = t.Assembly.GetType("System.Web.UI.DataSourceCache");
        MethodInfo m2 = t2.GetMethod("Invalidate", 
                        BindingFlags.Instance | BindingFlags.Public);
        m2.Invoke(cache, new object[] { key });
    }
    catch
    {
    }
}

(当然,文件开头需要 "using System.Reflection;")

这只是针对此问题的一个 hack。我花了超过一天的时间调试以找到这个奇怪问题的根源。

(附注:如果您找到更完善的解决方法,避免使用 Reflection, 告诉我。 谢谢!)

感谢 PlamenLeykov

您当然可以完全禁用 XmlDataSource 的缓存功能。它也运行良好。这是另一种简单的解决方案。

但是,如果你的情况就像我一样:更改的可能性低于其他回发可能性(例如,TreeView 很大,并且总是比数据源更改更频繁地触发回发),您将更喜欢使用 Reflection 而不是禁用缓存。

这是否是 Microsoft 的一个错误?

我不确定这是否是 Microsoft 的一个错误,或者它是否仅适用于设计规范。但是,实现是错误的,或者文档是错误的。

© . All rights reserved.