【问题标题】:Strange caching issues in Entity Framework 7Entity Framework 7 中的奇怪缓存问题
【发布时间】:2016-04-07 09:47:50
【问题描述】:

我遇到了一些非常具体的问题,想知道是否有人遇到过同样的问题。

我的 SQL 查询(在存储过程中)很简单,我已经简化了一点,但是:

BEGIN
        SELECT DISTINCT
            [ANU].[OldUserId] AS [ID]
            ,[ANU].[Email]
        FROM
            [dbo].[AspNetUsers] AS [ANU]
        INNER JOIN
            [dbo].[User] AS [U]
        ON
            [U].[ID] = [ANU].[OldUserId]
    END

很简单,直接通过SQL Management Studio运行SP就可以了。

但是,我通过实体框架运行它:

 [ResponseCache(Duration = 0)] // used this out of desperation
 public List<DriverDTO> GetByOrganisation(int organisationId, bool isManager)
 {
      return _context.Set<DriverDTO>().FromSql("dbo.New_User_List @OrganisationId = {0}, @IsManager = {1}", organisationId, isManager).ToList();
 }

DriverDTO:

public class DriverDTO
{
      [Key] // tried removing this also
      public int ID { get; set; }
      public string Email { get; set; }
}

它运行并返回结果,很好。但是,这些结果正在被缓存。第一次调用后对 SP 的每次调用都会返回相同的结果,即使我更新了记录。因此,假设我编辑了用户记录并更改了电子邮件 - 最初获取的电子邮件将始终被带回。

同样,通过 SQL 管理器运行 SP 会返回正确的结果,但我的 C#/EF 端没有。我脑子里唯一合乎逻辑的事情是,我迫切需要绕过的东西以某种方式被缓存在引擎盖下?!

【问题讨论】:

    标签: c# asp.net .net asp.net-mvc entity-framework


    【解决方案1】:

    您加载的实体缓存在DbContext 中(在每个DbSetLocal 集合中)。

    有几种选择:

    1. 使用AsNoTracking 进行查询:

      return _context.Set<DriverDTO>()
                 .AsNoTracking()
                 .FromSql("dbo.New_User_List @OrganisationId = {0}, @IsManager = {1}", organisationId, isManager)
                 .ToList();
      

      这应该避免实体框架为此查询完全缓存

    2. 为每个查询使用一个新的DbContext 实例

    3. 或者,在发出查询之前从上下文中分离所有缓存的实体......类似于(未经测试):

      _context.Set<DriverDTO>().Local.ToList().ForEach(x=>
      {
         _context.Entry(x).State = EntityState.Detached;
      });
      

      请注意,与人们的想法相反,您不能使用_context.Set&lt;DriverDTO&gt;().Local.Clear(),因为这会将您的实体标记为已删除(因此,如果您之后SaveChanges,它将从数据库中删除实体),因此,如果您正在尝试使用本地缓存,请小心。

    除非您需要使用单个 DbContext 或附加从 SP 接收到的实体,否则我会选择 #2。否则,我会选择#1。为了完整起见,我将 #3 放在那里,但除非绝对必要,否则我会避免使用本地缓存。

    【讨论】:

    • 今天你救了我的培根,谢谢! .AsNoTracking() 函数对我来说绝对是一种享受,并且是我的场景中最简单的方法。我只是希望这对其他人也有帮助。
    • @ChrisDixon 很高兴它有帮助。附带说明一下,AsNoTracking 查询比普通的 EF 查询要快得多,并且需要的内存不到一半...所以我会一直使用它,除非有理由不这样做(基本上,无论您的上下文将仅用于查询,而不是更新/删除)
    • 绝妙的建议。每天学习新的东西,会大大加快我的系统!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    • 1970-01-01
    • 2013-01-11
    • 2016-08-17
    • 2019-01-07
    • 1970-01-01
    相关资源
    最近更新 更多