gpt4 book ai didi

c# - 使用 Entity Framework 防止缓存对象最终出现在数据库中

转载 作者:太空宇宙 更新时间:2023-11-03 10:41:01 24 4
gpt4 key购买 nike

我们有一个带有 Entity Framework 和 SQL Azure 的 ASP.NET 项目。

我们的大部分数据每天只需要更新几次,其他数据非常不稳定。

  • 我们在启动时将几乎没有变化的数据缓存在内存中,从上下文中分离出来,而不是主要用于读取,从而大大减少了我们必须执行的数据库请求量。
  • 每次 Http 请求的 DbContext 都会请求 volatile 数据。
  • 当我们对缓存数据进行更新时,我们会向所有实例发送一条消息,以从 SQL 服务器捕获所有数据的最新版本。

到目前为止,还不错。

直到我们引入了一个错误,将这些“缓存”对象之一链接到“ volatile ”数据,并执行了 SaveChanges。

好吧,那真是一团糟。

每次更新都会再次再次添加整个数据树,用大量重复数据破坏整个数据库。

作为一个完整的 hack,我在其中一个根表上添加了一个带有 UniqueConstraint 和一些乱码数据的完全任意的列;希望下次我们引入此类错误时 SaveChanges() 失败,因为它会违反唯一约束。

但它当然是 hacky,我仍然很害怕 ;P有没有更好的方法来防止整个树的缓存对象最终出现在数据库中?

更多信息

  • 项目是 ASP.NET MVC
  • 我缓存这些数据,因为它主要是只读的,这可以为每个 http 请求节省大量额外的数据库调用
  • 这是一个高流量的网站,有很多个人定制的 View 。将 POCO 数据保存在内存中对我想要的非常有用。除了我提到的问题。
  • 它有点复杂,但一个简化版本是我通过单例缓存对象:所以即:

EntityCache.Instance.LolCats = new DbContext().LolCats.AsNoTracking().ToList();

我将这个缓存依赖注入(inject)到我的 Controller 中。

最佳答案

你可以这样解决:

1) 像这样创建一个界面:

public interface IIsReadOnly
{
bool IsReadOnly { get; set; }
}

2) 在所有可以缓存的实体中实现这个接口(interface)。当您读取和缓存它们时,将 IsReadOnly 属性设置为 true。调用 SaveChanges 时将使用此标志。请记住使用 [NotMapped] 属性修饰此属性,或使用任何其他方式让 EF 忽略它。

public class ACacheableEntitySample
: IIsReadOnly
{
[NotMapped]
public bool IsReadOnly { get; set; }

// define the "regular" entity properties
}

注意:您可以直接在类定义中包含属性(如果使用代码优先),或使用部分类(对于 Db First、Model First 或 Code First)。

注意:或者,您可以使用 Fluent API 或更好的方法让 EF 忽略 IsReadOnly 属性 a custom convention (EF 6+)

3) 覆盖继承的 DbContext.SaveChanges 方法。在覆盖的方法中,review all the entries with pending changes ,如果它们是只读的,将状态更改为 Unchanged:

if (entry is IIsReadOnly) // if it's a cacheable entity
{
if (entry.IsReadOnly) // and it was marked as readonly when caching
{
// change the entry state to unchanged here, so that it's not updated
}
}

注意:这是解释您需要做什么的示例代码。在您的最终实现中,您可以使用一个简单的 LINQ 语句来完成此操作,该语句获取所有 IIsReadOnly 实体,这些实体的 IsReadOnly 设置为 true,并将它们的状态设置为 不变

您可以在另一个 DbContext 中使用 IIsReadOnly 实体并以通常的方式操作它们。例如,如果您获得这些实体之一,对其进行更新,然后调用 SaveChanges,更改将被保存,因为 IsReadOnly 将具有默认的 false值(value)。但是您可以轻松避免意外保存缓存数据的更改,只需在缓存时将 IsReadOnly 属性设置为 true 即可。

关于c# - 使用 Entity Framework 防止缓存对象最终出现在数据库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25333698/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com