簡體   English   中英

ASP.NET 內核 - 更新緩存列表的 1 個元素<element>在 IMemoryCache 中使用 EF Core</element>

[英]ASP.NET Core - Update 1 Element of a cached List<Element> in IMemoryCache using EF Core

我正在使用ASP.Net Core (Razor Pages) 和EF Core構建一個網上商店。 為了加快大量計算,我緩存了所有產品(~100.000)。 信息來自我們的數據庫。

楷模

class ProductInformation{
    // some information about how to display a product
    public string productnumber {get; set;}
    public Product product {get; set;}
}

class Product{
    public string productnumber {get; set;}
    public decimal price {get; set;}
    public Category category {get; set}
    // and a lot more...
}

在我的 DBContext 中,我定義每個 PoductInformation都有一個確切的產品。

緩存方法

private readonly IMemoryCache _cache; // is set in the constructor
private readonly DBContext _dbContext; // is set in the constructor
public List<ProductInformation> GetProductInformationList(){
    List<ProductInformation> = _cache.GetOrCreate("ProductInformations", entry =>
    {
        entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24);
        List<ProductInformation> list =_dbContext.ProductInformation.ToList();
        // do a lot of calculations on the list-elements
        return list;
    });
}

整個緩存方法需要 100-120 秒。 現在另一個系統更新了我在數據庫中的一種產品價格,當然我想在我的網上商店中顯示該產品的正確價格。 假設我想每 15 分鍾檢查一次價格。

解決方案 - 嘗試但不滿意

方法一

我可以將整個列表的緩存設置為 15 分鍾,這會起作用,但這不是我想要的。 刷新整個緩存很慢而且沒有必要。 99.9% 的數據沒有改變。

方法二

在我的 model ProductInformation 中,我創建了一個更新產品的方法:

class ProductInformation{
    // some information about how to display a product
    public string productnumber {get; set;}
    public Product product {get; set;}

    pubic DateTime ProductTimeStamp {get; set;}
    public UpdateProduct(){
        // If ProductTimeStamp is more than 15 minutes in the past
        // get Product from the DB
        // and update the timestamp
    }
}

在我顯示 ProductInformation 的任何地方,我都會調用UpdateProduct() 然后我只重新檢查我展示的產品的“舊”價格。 這比重新計算整個緩存要有效得多。 但現在我需要在我的 ProductInformation 中建立一個數據庫連接(即緩存)。 我不能讓它工作。

方法三

由於方法 2 中的問題是我沒有數據庫連接,因此我可以在 model 之外采用UpdateProduct()方法並將其放入我有數據庫連接的存儲庫中。 在我顯示 ProdctInformation 的任何地方,我都需要調用類似_proudctRepository.UpdateProduct(ref ProductInformation); . 這個方法看起來像:

public void UpdateProduct(ref ProductInformation pi){
    pi.Product = _dbContext.Product.Where(p => p.productnumber == pi.productnumber);
   // Of course I also need to do the calculations from the caching-method in GetProductInformationList()
}

但這感覺不對。 實體框架為我組織了 ProductInformation 和 Product 之間的連接,那么是否可以通過這種方式重新定義 Product? 我認為這不是通往 go 的方式。

問題

我認為很多人在相同的情況下使用 IMemoryCaching(您只想更新緩存列表中的單個元素或緩存列表元素的某些元素(價格/股票/...))。 我們該如何處理呢?

1) 將LastChanged (datetime[offset]) 列添加到您的Product數據庫中,並在更新您的價格時詢問“另一個系統”是否也更新它。 這樣,您可以輕松地將Max(LastChanged)保存在緩存中並僅查詢更改的產品,從而減少更新時間和大小,並且可以更頻繁地執行此操作。

2)將數據放入緩存時添加AsNoTracking 您不會將它們更新回數據庫(我猜),因此不跟蹤會稍微加快一切。 此外,這將使您不必擔心ProductInformation - Product EF 關系,因為 EF 無論如何都不會跟蹤它們,並且pi.Product將是一個通常的對象持有屬性,沒有任何隱藏的魔法。

3) 在每個頁面渲染時檢查價格更新是不好的。 更新應該在其他線程/后台運行。 設置一些后台任務來檢查更新的價格並將更新的對象重新加載到緩存中 - 使用 (1) 您可以每 5 分鍾或更短時間運行一次更新。 通過依賴注入查看后台任務的 DbContext以獲取 DbContext。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM