运行存储过程后刷新存储库

时间:2015-09-15 11:36:49

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

我的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);
}

2 个答案:

答案 0 :(得分:7)

这是因为实体框架上下文已包含您的对象。方法Find(id)始终检查上下文中是否存在对象,如果存在,则Entity Framework将不会查询数据库。存储过程不会更改上下文对象,因为它们是直接针对数据库执行的,这就是您在实体中看不到更新值的原因。

您可以使用以下任一项解决此问题:

  1. 在上下文中停止实体跟踪
  2. 使用AsNoTracking()查询实体,而不进行跟踪。
  3. 执行存储过程后,使用First(...)FirstOrDefault(...)Single(...)等查询对象。
  4. 我建议你选择选项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查询新实体的数据库;
  • 请勿使用DbExtensions.AsNoTracking将实体首先附加到上下文。