2013-01-02 55 views
4

我們直接使用Azure緩存(而不是通過可用的實體框架包裝器之一)。顯然,對於分佈式緩存,我們需要序列化對象。不幸的是,這導致了用於導航屬性的延遲加載的基於DbContext的代理的問題。序列化Azure緩存的實體框架對象

我看到我們可以使用custom serializer爲了將代理映射到空集合(如果沒有加載)或到普通對象(如果加載),但我不確定實現。一個可能的實現可以基於the one used by WCF,但我不確定Azure是否以相同的方式工作。

理想的解決方案(這就是爲什麼我點ProxyDataContractResolver)將是其中,當序列發生了:

  • 如果導航屬性已經被加載,就好像它是一個正常的數據將被序列化收集,
  • 如果它們沒有加載,它們將不會被序列化(我希望延遲加載在反序列化之後爲後一種情況回來工作,但如果它沒有的話,它是可以接受的)。

是否有人用優雅的方式手動修復了這個問題?

在此先感謝!

回答

2

我會假設,如果您想緩存EF對象,則不需要延遲加載或更改這些實體的跟蹤。

我相信這些都是通過對象代理啓用,這將導致序列化問題(因爲你不想序列化代理)。

如果您禁用屬性DbContext.Configuration.ProxyCreationEnabled然後序列化實際的對象,而不是代理應該工作正常。當通過WCF返回POCO對象時,通常需要這樣做,但對於其他類似的串行化場景可能也是如此。

+0

其實這就是我想避免的解決方案,因爲 1)這意味着我需要修改所有的查詢緩存到不使用ProxyCreation 2)我必須做額外的代碼,以包括一些上述關係(這是我們的***架構的問題,不幸的是我們不能使用包括方法) 3)一旦我們找回了延遲加載OB ject緩存將是一件好事 我更新我的原始問題,以顯示此。 –

+0

抱歉沒有獲得賞金 - 我不知道我會完全失去積分 - 我想我可以在之後獎勵這些積分。現在我沒有足夠的;)。 –

1

如果您在序列化之前將DbContext從EF實體中分離出來,則會禁用延遲加載,因此您的自定義序列化程序不會嘗試序列化任何尚未屬於實體圖形的任何內容。

然後,當您從緩存中取回它時,如果將它附加到一個新的(相同的)DbContext,應該重新啓用延遲加載。 (注意:一旦將實體從上下文中分離出來,包含相同對象的任何新查詢都會創建一個新的附加副本,因此您需要謹慎編寫代碼以避免遇到多種潛在問題不過這就是說,這應該讓你做你想做的事。)

+0

我還沒有將此標記爲答案,以防有人知道我們可以通過配置常規高速緩存串行器來實現這一點。 –

+0

我相信你必須單獨分離通過導航屬性找到的對象 - Detach()不會傳播。如果你在其他地方沒有查詢記錄,最簡單的方法是使用DbContext.ObjectStateManager.GetObjectStateEntries()來提取通過上下文訪問的適當類型的實體列表,以及Detach()/從那裏緩存相關的內容。通過這種方式,您只會獲得已枚舉的列表,而不是通過直接訪問它們來枚舉導航屬性。 – Cerebrate

+0

這是非常困難的。我的Load方法幾乎沒有關於queryOnCacheMiss的知識。它知道Type是返回的對象,但不知道關聯的條目。 ObjectStateManager中的一個對象可能在那裏,因爲在該請求期間執行了另一個查詢,所以我需要回到Andy的建議。 –