2014-12-06 26 views
2

我在我的網站上預加載產品數據,因爲我需要這個快速訪問,並且寧願在應用程序啓動時加載一次,而不僅僅是當這是要求。這是確保加載速度快的一種方法。我通過將我的產品實體與其他一些實體一起加載並將它們存儲在內存中來做到這一點。當你不再有上下文引用時如何從上下文中分離實體

我再有類似以下內容檢索我的數據:

public override IEnumerable<Product> Get() 
{ 
    var result = _cacheManager.Get(PreLoadCacheKey) as IEnumerable<Product>; 
    if (result != null) 
     return result; 

    return base.Get(); 
} 

我現在面臨的問題是,我使用依賴注入,我無法控制我的數據上下文的範圍比(其它將其設置爲InstancePerRequest()並保留它),因此當我緩存我的實體時,它們仍然具有對原始上下文的引用。

我已經試過各種事情,但似乎無法避開的問題:

The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects. 

試圖附加從緩存中檢索到一個新的實體,我加入到數據庫中的實體時。

事情我已經嘗試:

  1. 使用AsNoTracking()
  2. 通過所有的結果循環檢索數據將它們添加到緩存和Detach從當前上下文荷蘭國際集團他們然後將它們連接到新的上下文之前從緩存中檢索。

理想情況下,我希望能夠從實體側面的實體中分離上下文,以便我可以看到實體是否附加到當前上下文,如果沒有,則將它從舊的一個並附加到新的。然而,從我所看到的,只有你可以將它分離出來,是通過參考我不會有的舊背景。

我錯過了一些明顯的東西嗎?

編輯

這是一個例子,我想實體連接到另一個背景:

var orderLine = order.Lines.FirstOrDefault(ol => ol.Product.Id == product.Id) ?? new SalesOrderLine(); 

orderLine.Price = price.Price; 
orderLine.Product = product; //This is my cache'd entity. 
orderLine.ProductPriceType = price.ProductPriceType; 
orderLine.Quantity += qty; 

order.Customer = customer; 
order.Lines.Add(orderLine); 
order.Status = SalesOrderStatus.Current; 

Update(order); 
SaveChanges(); 

由於它矗立在那一刻,我強行加載未緩存的版本來解決這個問題。

+0

請在出現此異常的位置顯示代碼。你在哪裏把一個'Product'與另一個實體聯繫起來? – 2014-12-06 20:08:09

+0

@GertArnold完成。 – webnoob 2014-12-06 20:11:34

回答

0

由於您無法控制您的上下文對象的生命週期,我認爲在加載時總是分離您的產品對象並在保存時附加它們是有意義的。

,所以當你的GET()方法被調用,而不是隻檢查緩存管理器,如果沒有找到從base.get返回()做下面的

public override IEnumerable<Product> Get() 
    { 
     var result = _cacheManager.Get(PreLoadCacheKey) as IEnumerable<Product>; 
     if (result != null) 
      return result; 


     return DetachAndReturn(); 
    } 

    private IEnumerable<Product> DetachAndReturn() 
    { 
     foreach (var product in base.Get()) 
     { 
      base.Detach(product); 
      yield return product; 
     } 
    } 
+0

感謝您的回覆。從內存中,當我在過去嘗試過這種方式時,將檢索到的緩存實體附加到當前上下文中,然後使緩存實體引用我當前的上下文,這意味着下一次從緩存中檢索它時,它又是引用舊的背景。這聽起來可能嗎?這可能是因爲我誤解了我之前嘗試過的這個問題。 – webnoob 2014-12-06 20:07:40

1

AsNoTracking檢索緩存的數據是第一步。但是(顯然)緩存中的對象被創建爲代理,所以他們知道已經被另一個上下文創建。

所以要確保沒有代理,但只是POCO的緩存,您可以通過在獲取的對象緩存上下文禁用代理的創建做:

db.Configuration.ProxyCreationEnabled = false; 

(其中dbDbContext實例) 。

然後確保在使用該對象之前,請將該對象附加到新的上下文中。這很重要,因爲如果您Add()新的OrderLine,EF可能會嘗試添加新的Product以及。

我想補充一點,這都將是如此容易得多,如果你在你的實體模型公開OrderLine.ProductId:剛纔設置的ID值就足夠了。

+0

感謝您的支持。關於你的最後一句話,在這種情況下,它是非常有意義的(我會這樣做),但我有另一個區域,允許編輯產品,所以我會得到當前正在編輯的產品,更改值,然後調用'更新(產品)',所以這在這種情況下不起作用。這個代理的東西聽起來很有希望,所以我會看看(奇怪,我以前沒有見過)。 – webnoob 2014-12-06 20:29:32

相關問題