gpt4 book ai didi

c# - 使 Entity Framework 缓存失效/禁用

转载 作者:可可西里 更新时间:2023-11-01 03:04:36 26 4
gpt4 key购买 nike

我看到有很多关于 EF 缓存的问题,但我还没有找到解决问题的方法。

直接的问题是

如何完全禁用 Entity Framework 6 缓存?或者,我能否以编程方式告诉 EF 忘记缓存,因为数据发生了一些变化?

背景

首先,我继承了一个应用程序,该应用程序由 EF(模型优先定义实体)和普通旧 SQL(操作数据)的奇怪组合组成。我所做的是重构应用程序,以便:

  • 使用 EF6 LINQ 进行简单的查询(例如实体的 GetAll())
  • 将复杂的数据操作留在 SQL 中,使用 DbContext.Database.Connection需要时
  • 添加Spring.Web支持启用 DI 和事务(尚未)

目前,我已经重新组织了代码,以便应用程序的主要功能(在庞大的数据集上运行复杂的 SQL 查询)像以前一样工作,但随后使用 as 更智能地完成查找域实体操作尽可能多的 Entity Framework

大多数....

我继承的其中一个页面是一个多复选框页面,为了更好地理解,我将向您展示。我不会讨论以前的实现者的选择,因为修复我当前的问题并在以后重构代码比阻止开发损坏的功能要便宜。

页面是这样的

enter image description here

基本上是 Controller方法如下

    [HttpPost]
public ActionResult Index(string[] codice, string[] flagpf, string[] flagpg, string[] flagammbce, string[] flagammdiv, string[] flagammest,
string[] flagintab, string[] flagfinanz, string[] flagita, string[] flagest, string pNew){
Sottogruppo2015Manager.ActivateFlagFor("pf", flagpf);
Sottogruppo2015Manager.ActivateFlagFor("pg", flagpg);
Sottogruppo2015Manager.ActivateFlagFor("ammbce", flagammbce);
Sottogruppo2015Manager.ActivateFlagFor("ammdiv", flagammdiv);
Sottogruppo2015Manager.ActivateFlagFor("ammest", flagammest);
Sottogruppo2015Manager.ActivateFlagFor("intab", flagintab);
Sottogruppo2015Manager.ActivateFlagFor("finanz", flagfinanz);
Sottogruppo2015Manager.ActivateFlagFor("ita", flagita);
Sottogruppo2015Manager.ActivateFlagFor("est", flagest);

return RedirectToAction("Index", new { pNew });
}

每个string[]参数是表中的一列。 ActivateFlagFor方法按顺序运行两个查询

UPDATE table SET --param1-- = 0;
UPDATE table SET --param1-- = 1 where id in (--param2--)

当缓存启动时

行为如下:

  • 我首先加载发出 LINQ 选择的页面:检查匹配列中的 1 和 0
  • 我更改一张或多张支票并提交
  • Controller 发出查询以更新数据库中的检查
  • 重定向(!意味着新请求!)以重新加载页面之前,我检查数据库并应用更改
  • 页面重新加载,发出上面相同的 LINQ 选择:显示旧检查

我确定这是缓存问题,因为重新加载应用程序可以解决问题。由于应用程序的主要功能完全基于 SQL,因此对查找表的更改会反射(reflect)到主要操作中,这是正确的行为。

我知道 EF 缓存是一个非常好的性能特性,但在我的情况下我只是不想使用它,至少在我将整个应用程序迁移到 LINQ DML 之前(可能是不可能的)。

我如何使用 DbContext

当然你们中的一些人可能会问“你如何使用你的 DbContext?” “你处理得当吗?”。

  • 我还没有在我的管理器类中集成 Spring 事务
  • 在数据库上执行操作 的每个对象都是一个I<Entity>Manager扩展 BaseManager
  • DbContext是一个请求范围的 Spring 对象。我已经asked about disposing request-scoped objects但我目前实现了一个解决方法,虽然不好,但在请求结束时正确处理 DbContext。

示例代码

public class ExampleManagerImpl : BaseManager, IExampleManager
{
public void ActivateFlagFor(string aFlag, string[] aList)
{
string sql = "UPDATE table SET flag" + aFlag + " = 0";
RunStatementV1(sql);

if (aList != null && aList.Any())
{
sql = "UPDATE table SET flag" + aFlag + " = 1 WHERE id in (" + aList.ToCsvApex() + ")";
RunStatementV1(sql);
}
}

public IList<Models.Example> GetAll()
{
return DataContext.example.ToList(); //I don't dispose of the DataContext willingly
}
}

public abstract class BaseManager {

public DbContext DataContext { get; set; } //Autowired

protected void RunStatementV1(string aSqlStatement)
{
IDbConnection connection = DataContext.Database.Connection;
if (connection.State == ConnectionState.Closed || connection.State == ConnectionState.Broken) connection.Open(); //Needed because sometimes I found the connection closed, even if I don't dispose of it
using (IDbCommand command = connection.CreateCommand())
{
command.CommandText = aSqlStatement;
command.ExecuteNonQuery();
}

}
}

我尝试了什么

最佳答案

如果您想完全忽略 EF6 的数据检索缓存,请将 AsNoTracking() 添加到查询的末尾(在调用 ToList() 或执行任何其他操作之前)这将执行查询。

MSDN on AsNoTracking()

请注意,这样做既不会检查现有数据的缓存,也不会将数据库调用的结果添加到缓存中。此外, Entity Framework 不会自动检测您从数​​据库中检索到的实体的更改。如果您确实想要更改任何实体并将它们保存回数据库,则需要在调用 SaveChanges() 之前附加更改的实体。

您的方法目前是:

public IList<Models.Example> GetAll()
{
return DataContext.example.ToList();
}

它会变成:

public IList<Models.Example> GetAll()
{
return DataContext.example.AsNoTracking().ToList();
}

如果您对处理 EF 缓存的其他选项感兴趣,我写了一个 blog post about EF6 Cache Busting .

关于c# - 使 Entity Framework 缓存失效/禁用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28233406/

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