usr*_*ΛΩΝ 16 c# linq caching entity-framework
我看到EF缓存有很多问题,但我找不到解决问题的方法.
如何完全禁用Entity Framework 6缓存?或者,我可以通过编程方式告诉EF忘记缓存,因为数据发生了什么变化?
首先,我继承了一个由EF(模型优先定义实体)和普通旧SQL(操纵数据)的奇怪混合构成的应用程序.我做的是重构应用程序,以便:
GetAll()实体)使用EF6 LINQDbContext.Database.Connection在需要时使用SQL中的复杂数据操作Spring.Web支持以启用DI和交易(尚未)在目前,我重新组织了代码,以便应用程序的主要功能(在大型数据集上运行复杂的SQL查询)像以前一样工作,但随后使用尽可能多的实体框架更智能地完成查找域实体操作
我继承的其中一个页面是一个多重复选框页面,我将向您展示最佳理解.我不会讨论之前的实现者的选择,因为修复我当前的问题和后来的重构代码比阻止破坏功能的开发更便宜.
这就是页面的样子

基本上该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 });
}
Run Code Online (Sandbox Code Playgroud)
每个string[]参数都是表中的一列.该ActivateFlagFor方法按顺序运行两个查询
UPDATE table SET --param1-- = 0;
UPDATE table SET --param1-- = 1 where id in (--param2--)
Run Code Online (Sandbox Code Playgroud)
以下是行为:
我确信这是一个缓存问题,因为重新加载应用程序可以解决问题.由于应用程序的主要功能完全基于SQL,因此对查找表的更改将反映到主操作中,这是正确的行为.
我知道EF缓存是性能的一个很好的功能,但在我的情况下我只是不想要它,至少在我将整个应用程序迁移到LINQ DML之前(可能是不可能的).
DbContext当然有些人可能会问"你如何使用你的DbContext?" "你正确处理它吗?"
I<Entity>Manager扩展BaseManagerDbContext是一个请求范围的Spring对象.我已经询问过处理请求范围的对象,但我目前实现了一种解决方法,虽然很糟糕,但在请求结束时正确处理了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
}
}
Run Code Online (Sandbox Code Playgroud)
和
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Detach似乎解决了这个问题,但是我需要将它应用到十几个实体,以便将来某天恢复Cod*_*hug 35
如果要完全忽略EF6的数据检索缓存,则添加AsNoTracking()到查询的末尾(在调用ToList()或执行任何其他可执行查询的操作之前).
请注意,这样做既不会检查现有数据的缓存,也不会将数据库调用的结果添加到缓存中.此外,实体框架不会自动检测您从数据库中检索的实体的更改.如果您确实想要更改任何实体并将其保存回数据库,则需要在调用之前附加更改的实体SaveChanges().
你的方法目前是:
public IList<Models.Example> GetAll()
{
return DataContext.example.ToList();
}
Run Code Online (Sandbox Code Playgroud)
它将改为:
public IList<Models.Example> GetAll()
{
return DataContext.example.AsNoTracking().ToList();
}
Run Code Online (Sandbox Code Playgroud)
如果您对处理EF缓存的其他选项感兴趣,我写了一篇关于EF6 Cache Busting的博客文章.
小智 5
我也有这个麻烦,但是我可以解决。
我正在使用存储库模式,并使用.Net Core的默认DI。我一直在使用AddSingleton(...),但是与DbContext一起使用是错误的。
因此,我已更改为AddScoped,就像我从docs中读取的:范围化的生存期服务每个请求创建一次。
它解决了我的问题。
| 归档时间: |
|
| 查看次数: |
25680 次 |
| 最近记录: |