C# 奇怪的实体框架行为-缓存?
我有ASP.NET MVC 4应用程序,使用EF 4.3进行迁移。我使用WebGrid帮助程序为系统用户显示详细信息:C# 奇怪的实体框架行为-缓存?,c#,entity-framework,caching,asp.net-mvc-4,webgrid,C#,Entity Framework,Caching,Asp.net Mvc 4,Webgrid,我有ASP.NET MVC 4应用程序,使用EF 4.3进行迁移。我使用WebGrid帮助程序为系统用户显示详细信息: @grid.GetHtml( headerStyle: "gridHeader", footerStyle: "gridFooter", firstText: "<< First", previousText: "< Previous", nextText: "Next >", lastText: "Last >>", alternatin
@grid.GetHtml(
headerStyle: "gridHeader",
footerStyle: "gridFooter",
firstText: "<< First",
previousText: "< Previous",
nextText: "Next >",
lastText: "Last >>",
alternatingRowStyle: "gridAlternativeRow",
columns: new[] {
grid.Column("Login", header: "User Login", canSort: true),
grid.Column("FullName", header: "User Name", canSort: true),
grid.Column("Email", header: "User Email", canSort: true),
grid.Column("Category", header: "User Category", canSort: true),
grid.Column(
"",
header: "",
format: @<text>
@Html.ActionLink("Edit", "Edit", new { id=item.Id} )
</text>
)
})
然后,它重定向到Index anction方法,该方法生成用户列表,并通过WebGrid Helper将其传递回视图
每次访问存储库时,我都会从DbContext对象中为用户获取最新的值:
public List<User> GetAllUsersWithoutAdmin()
{
return context.Users.Where(x => x.Id != 1).OrderBy(x => x.FullName).ToList();
}
public User GetUser(int userId)
{
return context.Users.FirstOrDefault(x => x.Id == userId);
}
public string UpdateUserDetails(User user)
{
string info;
try
{
User uUser = context.Users.FirstOrDefault(x => x.Id == user.Id);
uUser.Category = user.Category;
uUser.Email = user.Email;
uUser.FullName = user.FullName;
uUser.Login = user.Login;
context.SaveChanges();
info = "success";
}
catch (Exception err)
{
info = err.Message;
}
return info;
}
然后,每个存储库实现此接口:
private ActivityLogContext context;
public UserRepository(IUnitOfWork _context)
{
context = _context as ActivityLogContext;
}
并在线程范围内的同一上下文中共享它,该线程由AddBindings()方法在Ninject控制器工厂中实现:
private void AddBindings()
{
ninjectKernel.Bind().To();
ninjectKernel.Bind().To();
ninjectKernel.Bind().To();
ninjectKernel.Bind().To().InThreadScope();
}
一个问题: 出于某种奇怪的原因,在编辑用户对象时,上下文对象常常会为用户属性显示错误的值。它发生在DbContext和实际数据之间的某个EF级别上。特别是,SQL server中的数据总是正确的。看起来EF正在缓存以前的属性值,并获取这些值,而不是从数据库中获取这些值。我并没有观察到这种行为到底发生在什么时候,但它经常发生——每秒钟或第三次编辑对象。有时它会连续发生几次
我在以前的应用程序中使用了相同的设置,一切都很好。这次唯一的不同是我使用的是WebGrid Helper,只有带有WebGrid Helper的页面似乎会在我的应用程序中导致此问题???我也注意到了这种行为。为了演示,打开视图,直接在数据库中进行更改。砰的一声,你会发现变化并没有反映在你的观点中 EF会缓存数据,如果从dB读取的上下文也是您使用的写入dB的上下文,则EF只会“刷新”(此处的单词选择错误)此数据
希望这能给你指明正确的方向。我也注意到了这种行为。为了演示,打开视图,直接在数据库中进行更改。砰的一声,你会发现变化并没有反映在你的观点中 EF会缓存数据,如果从dB读取的上下文也是您使用的写入dB的上下文,则EF只会“刷新”(此处的单词选择错误)此数据
希望这为您指明了正确的方向。如果您尝试此操作,您的数据渲染是否正确 使用AsNoTracking加载实体:
public List<User> GetAllUsersWithoutAdmin()
{
return context.Users.AsNoTracking().Where(x => x.Id != 1)
.OrderBy(x => x.FullName).ToList();
}
public User GetUser(int userId)
{
return context.Users.AsNoTracking().FirstOrDefault(x => x.Id == userId);
}
这将为您提供在EF上下文中无法跟踪的分离实体,根据您的应用程序,这种方法可能是可接受的,也可能是不可接受的。即使您无法长期使用它,也可以尝试一下,看看问题是否真的是EF缓存。如果您尝试此操作,您的数据渲染是否正确 使用AsNoTracking加载实体:
public List<User> GetAllUsersWithoutAdmin()
{
return context.Users.AsNoTracking().Where(x => x.Id != 1)
.OrderBy(x => x.FullName).ToList();
}
public User GetUser(int userId)
{
return context.Users.AsNoTracking().FirstOrDefault(x => x.Id == userId);
}
这将为您提供在EF上下文中无法跟踪的分离实体,根据您的应用程序,这种方法可能是可接受的,也可能是不可接受的。即使您无法长期使用它,也可以尝试一下,看看问题是否真的是EF缓存。谢谢您的帮助。我仍然没有想到如何解决这个问题,因为我是通过编辑操作方法中的上下文进行更改的,所以应该反映出来谢谢帮助。我仍然没有想到如何解决这个问题,因为我是通过编辑操作方法中的上下文进行更改的,所以应该反映出来。如果它进行了任何更改,我将尝试。您的解决方案很有帮助!但我只能在你在回答中强调的两种方法中使用它。无法在编辑中使用它,因为我需要跟踪那里的更改。您的解决方案似乎解决了问题,但我仍然不知道是什么导致了问题。System.Data.EntityState.Detached在EF 6.1中成为System.Data.Entity.EntityState.Detached。如果它做了任何更改,我将尝试。您的解决方案很有帮助!但我只能在你在回答中强调的两种方法中使用它。无法在编辑中使用它,因为我需要跟踪那里的更改。您的解决方案似乎解决了问题,但我仍然不知道是什么导致了问题。System.Data.EntityState.Detached在EF 6.1中成为System.Data.Entity.EntityState.Detached
private ActivityLogContext context;
public UserRepository(IUnitOfWork _context)
{
context = _context as ActivityLogContext;
}
private void AddBindings()
{
ninjectKernel.Bind<IActivityRepository>().To<ActivityRepository>();
ninjectKernel.Bind<IUserRepository>().To<UserRepository>();
ninjectKernel.Bind<ICategoryRepository>().To<CategoryRepository>();
ninjectKernel.Bind<IUnitOfWork>().To<ActivityLogContext>().InThreadScope();
}
public List<User> GetAllUsersWithoutAdmin()
{
return context.Users.AsNoTracking().Where(x => x.Id != 1)
.OrderBy(x => x.FullName).ToList();
}
public User GetUser(int userId)
{
return context.Users.AsNoTracking().FirstOrDefault(x => x.Id == userId);
}
public string UpdateUserDetails(User user)
{
string info;
try
{
User uUser = context.Users.FirstOrDefault(x => x.Id == user.Id);
uUser.Category = user.Category;
uUser.Email = user.Email;
uUser.FullName = user.FullName;
uUser.Login = user.Login;
context.SaveChanges();
// detach the entity after saving it
Context.Entry(uUser).State = System.Data.EntityState.Detached;
info = "success";
}
catch (Exception err)
{
info = err.Message;
}
return info;
}