我正在使用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%的数据没有变化。
方法二
在我的模型 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 中的问题是我没有 DB 连接,因此我可以将UpdateProduct()
方法带出模型并将其放入我有 DB 连接的存储库中。在我显示 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?我认为这不是要走的路。
我认为很多人在相同的情况下使用 IMemoryCaching(您只想更新缓存列表中的单个元素或缓存列表元素的某些元素(价格/股票/...))。我们该如何处理?
1) 将LastChanged
(datetime[offset]) 列添加到您的Product
数据库中,并要求“另一个系统”在更新您的价格时也更新它。有了这个,您可以轻松地保存Max(LastChanged)
在缓存中并仅查询更改的产品,减少更新的时间和大小,并且您可以更频繁地执行此操作。
2)将数据放入缓存时添加AsNoTracking。您不会将它们更新回 DB(我猜),因此无跟踪会稍微加快速度。此外,这将使您无需担心ProductInformation
- Product
EF 关系,因为 EF 无论如何都不会跟踪它们,并且pi.Product
将是一个通常的对象保持属性,没有任何隐藏的魔法。
3) 在每个页面渲染时检查价格更新是不好的。更新应该在其他线程/后台运行。设置一些后台任务,以检查更新的价格并将更新的对象重新加载到缓存中 - 使用 (1) 您可以每 5 分钟或更短时间运行一次更新。在此处通过依赖注入检查DbContext 以获取后台任务以获取 DbContext。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句