我发现了一些非常具体的内容,并想知道是否有人面临同样的问题。
我的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 Manager运行SP会返回正确的结果,但我的C#/ EF端却没有。在我脑海中唯一合乎逻辑的事情就是某种东西以某种方式被缓存在我迫切需要绕过的引擎盖下?!
答案 0 :(得分:3)
您加载的实体会缓存在DbContext
(每个DbSet
的{{1}}集合中)。
有几种选择:
使用Local
查询:
AsNoTracking
这应该完全避免对此查询进行实体框架缓存
为每个查询使用新的return _context.Set<DriverDTO>()
.AsNoTracking()
.FromSql("dbo.New_User_List @OrganisationId = {0}, @IsManager = {1}", organisationId, isManager)
.ToList();
实例
或者,在发出查询之前从上下文中分离所有缓存的实体......类似于(未经测试):
DbContext
请注意,与您的想法相反,您无法使用_context.Set<DriverDTO>().Local.ToList().ForEach(x=>
{
_context.Entry(x).State = EntityState.Detached;
});
,因为这会将您的实体标记为已删除(因此,如果您_context.Set<DriverDTO>().Local.Clear()
之后,它就会被删除从数据库中删除实体),因此在尝试使用本地缓存时要小心。
除非您需要使用单个SaveChanges
或者已经收到SP附带的实体,否则我会选择#2。否则,我会去#1。我把#3放在那里是为了完整性,但除非有必要,否则我要避免使用本地缓存进行修改。