实体框架——跨多个上下文在内存中缓存对象

本文关键字:内存 缓存 对象 框架 实体 上下文 | 更新日期: 2023-09-27 18:01:14

我使用的是带有租户隔离应用程序的Entity Framework 6。我通过查看请求主机名来确定租户,然后在整个应用程序中使用它,在租户拥有的记录中设置它,等等。

每个上下文都会在请求结束时被处理。然而,因为租户查找非常频繁,所以我实际上只对每个主机名进行一次查找,然后将对象放入内存中的只读字典中。

这里的问题是,如果你什么都不做,你最终会得到与你的请求一样多的重复租户记录(无论如何,直到事情开始抛出,因为现在的查询不明确(。

我最初通过添加对DbSet的调用来解决这个问题。Attach((,并附加当前租户。然而,如果你同时有多个请求,你会得到一个异常,通知你不能将同一个对象附加到多个上下文:"一个实体对象不能被IEntityChangeTracker的多个实例引用。"由于我偶尔会在我的开发机器上访问页面过快而触发这个问题,我无法想象它适合生产。

我试着在保存之前添加这个调用来改变事情:

Context.ChangeTracker.Entries<Tenant>().Single().State = EntityState.Unchanged;

嗯,那也不管用。我得到错误"无法定义两个对象之间的关系,因为它们附加到不同的ObjectContext对象。">

好的。。。那么我是怎么做的?我所要做的就是(就最终的SQL结果而言(以不同的行结束,这些行具有对现有租户行PK的外键引用

我在引用EF4时发现的一些东西建议使用Detach方法,但我不确定我是否应该再调用它,因为它现在隐藏在DbSet的公共接口中。如果我是,我不确定在哪里。我第一次检索记录时?

edit:一个看起来确实有效的选项是转到上下文,根据缓存记录的ID提取租户记录。然而,现在我要去查询数据库,但没有真正的原因。

实体框架——跨多个上下文在内存中缓存对象

缓存数据的非更改跟踪、非实体透视图是否更有意义。租户记录似乎是指向外键关系的"指针"。

对我来说,逻辑如下:

  • 我有缓存的租户信息吗?不。。去拿并缓存
  • 现在我需要一些与租客有关的东西
    • 使用缓存的键关系执行实体上下文查询
    • 如果您确实需要租户记录,只需。在查询中包含("租户"(

在大多数情况下,似乎只需要保留映射到一个或多个主机名的租户id。采用老式的ADO方法,从缓存中剥离实体,只缓存所需的POCO数据。

这并不是很令人满意,但最终我发现这样做的方法是更改我的实体,以包含一个作为外键的属性:

[Required]
public Guid TenantId { get; set; }
[ForeignKey("TenantId")]
public virtual Tenant Tenant { get; set; }

然后,我可以从缓存中自由设置TenantId字段(因为它只是一个值类型,而不是EF生成的代理类(,而不必担心这个问题。