简体   繁体   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

I'm building a webshop using ASP.Net Core (Razor Pages) with EF Core .我正在使用ASP.Net Core (Razor Pages) 和EF Core构建一个网上商店。 To speed up a lot of calculation, I cache all the products (~100.000).为了加快大量计算,我缓存了所有产品(~100.000)。 The information is coming from our db.信息来自我们的数据库。

Models楷模

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

In my DBContext I define that every PoductInformation has exact one Product.在我的 DBContext 中,我定义每个 PoductInformation都有一个确切的产品。

The caching method缓存方法

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

The whole caching method takes 100-120 seconds.整个缓存方法需要 100-120 秒。 Now another system updates my price in the DB for one product and of course I want to show the correct price of that product on my webshop.现在另一个系统更新了我在数据库中的一种产品价格,当然我想在我的网上商店中显示该产品的正确价格。 Let's assume I want to check the price every 15 minutes.假设我想每 15 分钟检查一次价格。

Solutions - tried but not satisfying解决方案 - 尝试但不满意

Method 1方法一

I can set caching of the whole list to 15 minutes, that will work, but it's not what I want.我可以将整个列表的缓存设置为 15 分钟,这会起作用,但这不是我想要的。 Refreshing the whole cache is slow and not necessary.刷新整个缓存很慢而且没有必要。 99.9% of the data has not changed. 99.9% 的数据没有改变。

Method 2方法二

Inside my model ProductInformation I make a method that updates the Product:在我的 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
    }
}

Everywhere I display a ProductInformation, I call UpdateProduct() .在我显示 ProductInformation 的任何地方,我都会调用UpdateProduct() Then I only re-check the 'old' prices from products that I display.然后我只重新检查我展示的产品的“旧”价格。 This is much more efficiënt than recalculate the whole cache.这比重新计算整个缓存要有效得多。 But now I need a DB connection inside my ProductInformation (that is cached).但现在我需要在我的 ProductInformation 中建立一个数据库连接(即缓存)。 I can't get this to work.我不能让它工作。

Method 3方法三

Since the problem in method 2 is that I don't have a DB connection, I can take the UpdateProduct() method outside the model and put it in my repository where I have a DB connection.由于方法 2 中的问题是我没有数据库连接,因此我可以在 model 之外采用UpdateProduct()方法并将其放入我有数据库连接的存储库中。 Everywhere I display a ProdctInformation, I need to call something like _proudctRepository.UpdateProduct(ref ProductInformation);在我显示 ProdctInformation 的任何地方,我都需要调用类似_proudctRepository.UpdateProduct(ref ProductInformation); . . This method looks like:这个方法看起来像:

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()
}

But this feels not right.但这感觉不对。 The Entity Framework has organized for me the connection between ProductInformation and Product, is it then possible to redefine Product this way?实体框架为我组织了 ProductInformation 和 Product 之间的连接,那么是否可以通过这种方式重新定义 Product? I think its not the way to go.我认为这不是通往 go 的方式。

Question问题

I think a lot of people use IMemoryCaching for equal situations (where you want to update just a single element in a cached List or just some elements (price / stock /...) of a cached list element).我认为很多人在相同的情况下使用 IMemoryCaching(您只想更新缓存列表中的单个元素或缓存列表元素的某些元素(价格/股票/...))。 How can we handle this?我们该如何处理呢?

1) Add LastChanged (datetime[offset]) column to your Product database and ask "another system" update it too when it updates your price. 1) 将LastChanged (datetime[offset]) 列添加到您的Product数据库中,并在更新您的价格时询问“另一个系统”是否也更新它。 With this, you can easily save Max(LastChanged) in your cache and query only for changed Products, reducing time and size of updates, and you can do it more frequently.这样,您可以轻松地将Max(LastChanged)保存在缓存中并仅查询更改的产品,从而减少更新时间和大小,并且可以更频繁地执行此操作。

2) Add AsNoTracking when putting data into cache. 2)将数据放入缓存时添加AsNoTracking You will not update them back to DB (I guess), so no-tracking will speed up everything a little.您不会将它们更新回数据库(我猜),因此不跟踪会稍微加快一切。 Also, this will give you no-worry about ProductInformation - Product EF relations, because EF will not be tracking them anyway and pi.Product will be a usual object-holding property without any hidden magic.此外,这将使您不必担心ProductInformation - Product EF 关系,因为 EF 无论如何都不会跟踪它们,并且pi.Product将是一个通常的对象持有属性,没有任何隐藏的魔法。

3) It's not good to check for price updates on every page render. 3) 在每个页面渲染时检查价格更新是不好的。 Updates should run in other thread / background.更新应该在其他线程/后台运行。 Setup some background task that will check for updated prices and reload updated objects into cache - with (1) you can run updates every 5 minutes or less.设置一些后台任务来检查更新的价格并将更新的对象重新加载到缓存中 - 使用 (1) 您可以每 5 分钟或更短时间运行一次更新。 Check here DbContext for background tasks via Dependency Injection for obtaining DbContext. 通过依赖注入查看后台任务的 DbContext以获取 DbContext。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么在ASP.Net Core中获取IMemoryCache的多个实例? - Why getting multiple instances of IMemoryCache in ASP.Net Core? 在 ASP.net 核心应用程序中使用 IMemoryCache 和 Unity DI Container - Use IMemoryCache with Unity DI Container in ASP.net core application XUnit如何模拟IMemoryCache ASP.NET Core - XUnit how to mock IMemoryCache ASP.NET Core ASP.NET 内核将带 IMemoryCache 的内存缓存转换为 Redis - ASP.NET Core Converting In-Memory Cache with IMemoryCache to Redis 如果*不*注入依赖项,是否可以在 ASP.NET Core 中使用 IMemoryCache? - Possible to use IMemoryCache in ASP.NET Core if it is *not* dependency injected? 测试ASP.NET Core IMemoryCache的正确方法 - Proper way of testing ASP.NET Core IMemoryCache 无法通过UserManager更新用户 <TUser> 在asp.net core 2.2应用程序中使用ef core 2.2 - unable to update user via UserManager<TUser> using ef core 2.2 in asp.net core 2.2 app 将DBContext放入IMemoryCache(.NET Core / EF Core)之后为什么要处理它 - Why is DBContext is disposed after putting it in IMemoryCache (.NET Core / EF Core) 用户登录时如何显示 HTML 元素。(ASP.NET Core MVC,无 EF) - How to display HTML element when user is logged in. (ASP.NET Core MVC, without EF) 如何使用 EF Core 更新 ASP.NET 5 中的 dbcontext 脚手架? - How to update dbcontext scaffolding in ASP.NET 5 with EF Core?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM