简体   繁体   English

使用Entity-Framework更新异常?

[英]Update Exception with Entity-Framework?

Hi, 嗨,

I am using EntityFramework for my ASP.NET MVC website but have some problems with the update. 我在我的ASP.NET MVC网站上使用EntityFramework但是在更新时遇到了一些问题。

This is how my update code looka like : 这是我的更新代码的样子:

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;

When executing the context.Refresh i get the following exception : 执行context.Refresh时,我得到以下异常:

The element at index 0 in the collection of objects to refresh has a null EntityKey property value or is not attached to this ObjectStateManager. 要刷新的对象集合中索引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 

This is not the first time I get this problem. 这不是我第一次遇到这个问题。 First I thought that it might have to do with the relations in the database but after these was removed from the effected table the same exception remained. 首先,我认为它可能与数据库中的关系有关,但在从受影响的表中删除之后,仍然存在相同的异常。

Where does the adCategoryFilter come from? adCategoryFilter来自哪里?

The adCategoryFilter is instansiated(new) and then filled with data from the ViewObject(from the website). adCategoryFilter是instansiated(新),然后填充ViewObject(来自网站)的数据。 It does have the required data like filter Id (to map the filter to correct row in db). 它确实具有所需的数据,如过滤器ID(将过滤器映射到db中的正确行)。

Pleas explain why Im getting this problem and how I could solve it. 请求解释为什么我会遇到这个问题以及如何解决它。

BestRegards 最好的祝福

Because your using ASP.NET MVC, your working in a stateless environment. 因为您使用的是ASP.NET MVC,所以您在无状态环境中工作。 That means, once a request has finished processing, there is no more "Entity Framework Memory", or "The Graph". 这意味着,一旦请求完成处理,就不再有“实体框架内存”或“图形”。

So, you need to explicitly tell EF you wish to add or update. 因此,您需要明确告诉EF您希望添加或更新。

Here's how you do it: 这是你如何做到的:

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();
}

That is referred to as the stub technique. 这被称为存根技术。

In short, you create a new entity with the same entity key as the entity you are trying to UPDATE (in your case, the entity key is "Id"). 简而言之,您创建一个新实体,其实体键与您尝试更新的实体相同(在您的情况下,实体键是“Id”)。

You then "attach" this stub (so it's tracked by the EF internal graph), then override the values on this stub with your entity to UPDATE, then save changes. 然后,您“附加”此存根(因此它由EF内部图表跟踪),然后覆盖此存根上的值,并将您的实体更新为UPDATE,然后保存更改。

I can't use UpdateModel , as i have a multi-layered architecture and use POCO's, custom viewmodels, etc - so i have created a custom "UpdateModel" method on my service/repository - which does a (more complicated) version of the above. 我不能使用UpdateModel ,因为我有一个多层架构并使用POCO,自定义视图模型等 - 所以我在我的服务/存储库上创建了一个自定义的“UpdateModel”方法 - 它做了一个(更复杂的)版本的以上。

Also try not to use "if Id < 1, it's an add" with ASP.NET MVC - as if you forget to bind the ID on the view, it will be passed as 0, so even though you could be doing an update , your above code will try and do an add . 也尝试不使用“如果Id <1,它是一个添加”与ASP.NET MVC - 好像你忘了绑定视图上的ID,它将被传递为0,所以即使你可以做一个更新 ,您的上述代码将尝试添加

Instead be more explicit - have seperate action methods for Add/Update. 而是更明确 - 为添加/更新提供单独的操作方法。

HTH. HTH。

Instead of refreshing, try retrieving the object and updating its properties using something like an auto-mapper (or UpdateModel in MVC controller) 而不是刷新,尝试使用类似自动映射器(或MVC控制器中的UpdateModel)之类的东西检索对象并更新其属性

The EntityKey is a separate thing to the id property, with some other stuff going on under the hood. EntityKey是id属性的一个独立的东西,其他一些东西在幕后进行。 Your newly created object is missing this stuff, which is where the problem is coming from. 你新创建的对象缺少这个问题,这就是问题所在。

The pattern goes a little like (not a C# guy so please excuse syntax): 模式有点像(不是C#家伙所以请原谅语法):

var context = new MyEntities();
var originalObject = context.MyObjectSet.Single(x => x.Id == viewmodel.Id);
UpdateModel(originalObject);
context.SaveChanges();

The crucial difference is that the newly retrieved object has got the EntityKey all set correctly. 关键的区别在于新检索的对象已正确设置了EntityKey。 You can validly use the id property to detect a new/existing object, but there is more to the EntityKey than just that property. 您可以有效地使用id属性来检测新的/现有对象,但EntityKey不仅仅是该属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM