【问题标题】:Data Access Layer - static list objects and caching数据访问层 - 静态列表对象和缓存
【发布时间】:2011-02-10 12:15:39
【问题描述】:

我正在使用 .net MVC 开发一个网站

我有一个数据访问层,它基本上由从我的数据库中的数据创建的静态列表对象组成。

重建此数据的方法首先清除所有列表对象。一旦它们为空,然后添加数据。这是我正在使用的列表之一的示例。它是一种生成所有英国邮政编码的方法。在我的应用程序中有大约 50 种与此类似的方法,它们返回各种信息,例如城镇、地区、成员、电子邮件等。

public static List<PostCode> AllPostCodes = new List<PostCode>();
  1. 当调用rebuild方法时,它首先清除列表。

    ListPostCodes.AllPostCodes.Clear();

  2. 接下来,它通过调用 GetAllPostCodes() 方法重新构建数据

    /// <summary>
    /// static method that returns all the UK postcodes
    /// </summary>
    public static void GetAllPostCodes()
    {
        using (fab_dataContextDataContext db = new fab_dataContextDataContext())
        {
            IQueryable AllPostcodeData = from data in db.PostCodeTables select data;
    
            IDbCommand cmd = db.GetCommand(AllPostcodeData);
            SqlDataAdapter adapter = new SqlDataAdapter();
            adapter.SelectCommand = (SqlCommand)cmd;
            DataSet dataSet = new DataSet();
    
            cmd.Connection.Open();
            adapter.FillSchema(dataSet, SchemaType.Source);
            adapter.Fill(dataSet);
            cmd.Connection.Close();
    
            // crete the objects
            foreach (DataRow row in dataSet.Tables[0].Rows)
            {
                PostCode postcode = new PostCode();
                postcode.ID = Convert.ToInt32(row["PostcodeID"]);
                postcode.Outcode = row["OutCode"].ToString();
                postcode.Latitude = Convert.ToDouble(row["Latitude"]);
                postcode.Longitude = Convert.ToDouble(row["Longitude"]);
                postcode.TownID = Convert.ToInt32(row["TownID"]);
    
                AllPostCodes.Add(postcode);
                postcode = null;
            }
        }
    }
    

重建每 1 小时进行一次。这可确保网站每 1 小时拥有一组新的缓存数据。

我遇到的问题是,有时如果在重建期间,服务器会被请求击中并引发异常。例外是“索引超出了数组的范围”。这是由于在清除列表时。

ListPostCodes.AllPostCodes.Clear(); - // throws exception - although its not always in regard to this list.

一旦抛出此异常,应用程序就会死掉,所有用户都会受到影响。我必须重新启动服务器才能修复它。

我有 2 个问题...

  1. 如果我使用缓存而不是静态对象会有所帮助吗?
  2. 我有什么办法可以说“在重建过程中,等待它完成,直到接受请求”

任何帮助都是最合适的 ;)

真正的吉利

【问题讨论】:

  • 最正确的解决方案是避免使用不好的静态方法。我的意思是,总是很糟糕。即使你认为没问题,也要三思而后行,因为这很糟糕。如果您使用它们,请记住 Web 应用程序请求可能同时在不同的线程上。然后,了解静态数据和线程,并再次决定是否需要它们。

标签: asp.net-mvc caching data-access-layer


【解决方案1】:

1 如果我使用缓存而不是 静态对象会有帮助吗?

是的,您所做的所有事情都可以通过 ASP.NET 中内置的缓存功能更轻松地完成

有什么办法可以说“虽然 重建正在进行中,等待它 在接受请求之前完成”

常见的模式是这样的:

  1. 您从数据层请求数据

  2. 如果数据层看到缓存中有数据,那么它会从缓存中提供数据 如果缓存中没有数据,则从数据库请求数据并将其放入缓存中。之后将其提供给客户

清除缓存时有规则(CacheDependency 和 Timeout)。

最简单的解决方案是您坚持这种模式:这样第一个请求将访问数据库,而其他请求则从缓存中获得服务。您通过实现 SQLCacheDependency 来触发刷新

【讨论】:

  • 我将实施您的建议,一旦到位,如果我遇到任何问题,请查看同步和线程 cmets,谢谢
【解决方案2】:

您必须确保您的列表没有被一个线程修改,而其他线程正在尝试使用它。即使您使用 ASP.NET 缓存,这也是一个问题,因为集合不是线程安全的。一种方法是使用 SynchronizedCollection 而不是 List。然后确保在访问集合时使用如下代码:

lock (synchronizedCollection.SyncRoot) {
    synchronizedCollection.Clear();
    etc...
}

您还必须在阅读集合时使用锁定。如果您正在枚举它,您可能应该在这样做之前制作一个副本,因为您不想长时间锁定。例如:

List<whatever> tempCollection;
lock (synchrnonizedCollection.SyncRoot) {
    tempCollection = new List<whatever>(synchronizedCollection);
}
//use temp collection to access cached data

另一种选择是创建一个 ThreadSafeList 类,该类在内部使用锁定来使列表对象本身是线程安全的。

【讨论】:

    【解决方案3】:

    我同意 Tom 的观点,您必须进行同步才能完成这项工作。可以提高性能的一件事是在您实际从数据库中接收到新值之前不清除列表:

    // Modify your function to return a new list instead of filling the existing one.
    public static List<PostCode> GetAllPostCodes()
    {
        List<PostCode> temp = new List<PostCode>();
        ...
        return temp;
    }
    

    当你重建数据时:

    List<PostCode> temp = GetAllPostCodes();
    AllPostCodes = temp;
    

    这确保您的缓存列表在 GetAllPostCodes() 执行时仍然有效。它还有一个优点是你可以使用只读列表,这使得同步更容易一些。

    【讨论】:

      【解决方案4】:

      在您的情况下,您需要每隔一小时刷新一次数据。

      1) IT 应使用将绝对到期时间设置为 1 小时的缓存,因此它每 1 小时到期一次。在使用它之前检查缓存,通过执行 NULL 检查。如果它的 NULL 从 DB 获取数据并填充缓存。

      2) 使用上述方法的缺点是数据可能会过时 1 小时。因此,如果您始终想要最新的数据,请使用 SQLCacheDependency (PUSH)。所以每当你使用的选择命令发生变化时,缓存将从数据库中刷新并更新数据。

      【讨论】:

        猜你喜欢
        • 2010-11-23
        • 1970-01-01
        • 2010-11-18
        • 1970-01-01
        • 1970-01-01
        • 2011-08-02
        • 2018-11-10
        • 2011-05-08
        • 2014-09-04
        相关资源
        最近更新 更多