使用Entity-Framework更新异常?

Ban*_*hee 3 c# asp.net-mvc entity-framework .net-4.0

嗨,

我在我的ASP.NET MVC网站上使用EntityFramework但是在更新时遇到了一些问题.

这是我的更新代码的样子:

using (BissEntities context = new BissEntities())
    {

      if (adCategoryFilter.Id < 1)
        context.AddToAdCategoryFilter(adCategoryFilter);
      else
        context.Refresh(System.Data.Objects.RefreshMode.ClientWins, adCategoryFilter);

      if (context.SaveChanges() > 0)
        return true;
    }
    return false;
Run Code Online (Sandbox Code Playgroud)

执行context.Refresh时,我得到以下异常:

要刷新的对象集合中索引0处的元素具有null EntityKey属性值,或者未附加到此ObjectStateManager.

Stacktrace :    at System.Data.Objects.ObjectContext.RefreshCheck(Dictionary`2 entities, Object entity, EntityKey key)
   at System.Data.Objects.ObjectContext.AddRefreshKey(Object entityLike, Dictionary`2 entities, Dictionary`2 currentKeys)
   at System.Data.Objects.ObjectContext.RefreshEntities(RefreshMode refreshMode, IEnumerable collection)
   at System.Data.Objects.ObjectContext.Refresh(RefreshMode refreshMode, Object entity)
   at Biss.Models.FilterModel.UpdateCategoryFilter(AdCategoryFilter adCategoryFilter) in C:\Users\Snowman\Documents\Visual Studio 2010\Projects\Biss\Biss\Models\FilterModel.cs:line 86 
Run Code Online (Sandbox Code Playgroud)

这不是我第一次遇到这个问题.首先,我认为它可能与数据库中的关系有关,但在从受影响的表中删除之后,仍然存在相同的异常.

adCategoryFilter来自哪里?

adCategoryFilter是instansiated(新),然后填充ViewObject(来自网站)的数据.它确实具有所需的数据,如过滤器ID(将过滤器映射到db中的正确行).

请求解释为什么我会遇到这个问题以及如何解决它.

最好的祝福

RPM*_*984 5

因为您使用的是ASP.NET MVC,所以您在无状态环境中工作.这意味着,一旦请求完成处理,就不再有"实体框架内存"或"图形".

因此,您需要明确告诉EF您希望添加或更新.

这是你如何做到的:

using (BissEntities context = new BissEntities())
{
  if (adCategoryFilter.Id < 1)
    context.AdCategoryFilters.AddObject(adCategoryFilter);
  else {
     var stub = new AdCategoryFilters { Id = adCategoryFilter.Id };
     context.AdCategoryFilters.Attach(stub);
     context.AdCategoryFilters.ApplyCurrentValues(adCategoryFilter);
  }

  context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

这被称为存根技术.

简而言之,您创建一个新实体,其实体键与您尝试更新的实体相同(在您的情况下,实体键是"Id").

然后,您"附加"此存根(因此它由EF内部图表跟踪),然后覆盖此存根上的值,并将您的实体更新为UPDATE,然后保存更改.

我不能使用UpdateModel,因为我有一个多层架构并使用POCO,自定义视图模型等 - 所以我在我的服务/存储库上创建了一个自定义的"UpdateModel"方法 - 它做了一个(更复杂的)版本的以上.

也尝试不使用"如果Id <1,它是一个添加"与ASP.NET MVC - 好像你忘了绑定视图上的ID,它将被传递为0,所以即使你可以做一个更新,您的上述代码将尝试添加.

而是更明确 - 为添加/更新提供单独的操作方法.

HTH.