2013-01-24 34 views
0

我有一個調用外部API來獲取數據的MVC 3應用程序。該API返回XML,然後將其序列化爲對象。其中一些對象不會在一整天內改變,所以我緩存它們以減少開銷。我的問題是,如果我從緩存中取出某個項目並對其進行操作,它也會更改緩存的值。我認爲這是因爲只返回了對緩存項目的引用。我正在使用System.Web.HttpRuntime.Cache來緩存對象。有沒有辦法從緩存中返回一個項目作爲一個不可變的對象?或者輕鬆返回對象的克隆?我嘗試將緩存的值反序列化回XML,然後將其序列化爲一個新對象,儘管這樣做有效,但它會增加很多開銷並導致網站在負載下執行得非常糟糕。我可以爲每個項目實現ICloneable,但是接下來我必須爲每個類編寫一個深層克隆方法,這需要花費很多時間,並且序列化可能會產生相同的開銷問題。我想知道是否有更快的方法。MVC 3:從緩存中返回不可變對象

可以說我有一個緩存的人員列表。如果我這樣做:

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

這將從視圖和緩存列表中刪除姓氏不是Smith的所有人。該項目的未來獲取將只返回史密斯。

我可以通過做解決這個問題:

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; 
} 

回答

0

這是因爲你使用List集合類型。列表提供當前集合的參考。如果您不想修改緩存集合,則必須複製集合並運行過濾器。或者從緩存中返回無法修改當前集合並且執行過濾器之類的必要事情。

如果你需要它的例子,請讓我知道。