【问题标题】:MVC 3: Return immuteable objects from cacheMVC 3:从缓存中返回不可变对象
【发布时间】:2013-01-24 21:00:10
【问题描述】:

我有一个 MVC 3 应用程序,它调用外部 API 来获取数据。 API 返回 XML,然后我将其序列化为对象。其中一些对象在一天中不会更改,因此我将它们缓存以减少开销。我的问题是,如果我从缓存中取出一个项目并对其进行操作,它也会更改缓存的值。我认为这是因为只返回对缓存项的引用。我正在使用 System.Web.HttpRuntime.Cache 来缓存对象。有没有办法将缓存中的项目作为不可变对象返回?或者轻松返回对象的克隆?我尝试将缓存的值反序列化回 XML,然后将其序列化为一个新对象,尽管这可行,但它增加了很多开销,并导致站点在负载下执行得很差。我可以为每个项目实现 ICloneable,但是我必须为我的每个类编写一个深度克隆方法,这将花费大量时间并且可能会产生与序列化相同的开销问题。我想知道是否有更快的方法。

假设我有一个缓存的人员列表。如果我这样做:

var people = Cache.Get<List<Person>>("people");
people.Remove(p => p.LastName != "Smith");
return View(people);

这将从视图和缓存列表中删除姓氏不是 Smith 的所有人员。该项目的未来获取将仅返回 Smiths。

我可以通过以下方式解决这个问题:

var people = Cache.Get<List<Person>>("people");
var viewlist = people.Where(p => p.LastName == "Smith").ToList();
return View(viewlist);

这不会影响缓存的值。显然,我可以在代码中的任何地方执行此操作,但考虑到我缓存的项目数量,我必须确保每次都执行此操作。如果我尝试编辑从缓存中获取的对象,如果我可以让代码抛出编译时(甚至是运行时)错误,那就更好了。

我的缓存方法:

static object lockobj = new object();
public static T Get<T>(string index) //where T : new()
{
    T data;
    lock (lockobj)
    {
        data = (T)_cache[index];
    }
    return data;
}

public static T CacheInsert<T>(T obj, string index, CacheDependency dependencies,
        DateTime absoluteExpiration, TimeSpan slidingExpiration,
        CacheItemPriority priority, CacheItemRemovedCallback callback)
{
    T data;
    lock (lockobj)
    {
        data = (T)_cache[index];
        if (data == null)
        {
            _cache.Insert(index, obj, dependencies, absoluteExpiration, slidingExpiration, priority, callback);
            data = obj;
        }
    }
    return data;
}

【问题讨论】:

    标签: asp.net-mvc-3 c#-4.0 caching


    【解决方案1】:

    这是因为您使用的 List 集合类型。列表提供对当前集合的引用。如果您不想修改缓存集合,则必须复制您的集合并运行过滤器。或者从不允许修改当前集合的缓存中返回 ienumarable 并执行过滤器之类的必要操作。

    如果你需要它的例子,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 2021-10-11
      相关资源
      最近更新 更多