我的WebAPI项目中有以下操作,它运行存储过程来更新(以及其他一些操作)People
表:
public HttpResponseMessage SetAsMain(int id)
{
People people = repository.GetById(id);
if (people == null)
{
return ErrorMsg(HttpStatusCode.NotFound, string.Format("No people with ID = {1}", id));
}
if (people.IsMain)
{
return ReturnMsg(HttpStatusCode.OK, string.Format("{0} is already set as main", people.FullName));
}
try
{
var parameters = new Dictionary<string, string>();
parameters.Add("PeopleID", id.ToString());
repository.ExecProcedure("usp_PeopleSetMain", parameters);
return Request.CreateResponse(HttpStatusCode.OK, repository.GetById(id));
}
catch (Exception ex)
{
return ErrorMsg(HttpStatusCode.InternalServerError, ex.Message);
}
}
我在使用存储过程更新后检索数据时遇到问题。在这个地方:
return Request.CreateResponse(HttpStatusCode.OK, repository.GetById(id));
我获得的数据与更新前的数据相同。但是当我再次调用这个方法时,会有一个实际的数据。
如何刷新存储库中的数据?
您能告诉我为什么repository.GetById(id)
永远不会在ExecProcedure
之后提取新数据。
如果我必须添加更多信息,请告诉我
更新
方法GetById在我的存储库中:
public T GetById(object id)
{
return context.Set<T>().Find(id);
}
答案 0 :(得分:7)
这是因为实体框架上下文已包含您的对象。方法Find(id)
始终检查上下文中是否存在对象,如果存在,则Entity Framework将不会查询数据库。存储过程不会更改上下文对象,因为它们是直接针对数据库执行的,这就是您在实体中看不到更新值的原因。
您可以使用以下任一项解决此问题:
AsNoTracking()
查询实体,而不进行跟踪。First(...)
,FirstOrDefault(...)
,Single(...)
等查询对象。我建议你选择选项1或2.选项1:
context.Entry(people).State = EntityState.Detached;
如果您运行早期版本的Entity Framework,则应该分离对象:
context.People.Detach(people);
(非常感谢ieaglle)您还可以立即查询实体关闭跟踪(选项2):
context.People.AsNoTracking().FirstOrDefault(p => p.Id == id);
答案 1 :(得分:1)
DbSet.Find表现得更好:
如果上下文中存在具有给定主键值的实体,则会立即返回该实体而不向商店发出请求。否则,向具有给定主键值的实体的商店发出请求,并且如果找到该实体,则将该实体附加到上下文并返回。如果在上下文或商店中找不到实体,则返回null。
因此,Find
不会向您的新更新实体查询数据库,它只需要缓存旧实体。
要解决此功能,您可以选择以下几种方法:
.FirstOrDefault
,.SingleOrDefault
或任何其他触发查询执行的方法,显式强制EF查询新实体的数据库;