C# 是否使用实体框架更新异常?
你好, 我正在为我的ASP.NET MVC网站使用EntityFramework,但在更新时遇到一些问题 这就是我的更新代码的样子:C# 是否使用实体框架更新异常?,c#,asp.net-mvc,entity-framework,.net-4.0,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.Refr
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;
这不是我第一次遇到这个问题。首先,我认为这可能与数据库中的关系有关,但在从受影响的表中删除这些关系之后,仍然存在相同的异常
adCategoryFilter来自哪里?
adCategoryFilter被实例化(新建),然后填充来自ViewObject(来自网站)的数据。它确实具有所需的数据,如筛选器Id(将筛选器映射到db中正确的行)
请解释我为什么会遇到这个问题,以及我如何解决它
BestReleases不要刷新,而是尝试使用自动映射器(或MVC控制器中的UpdateModel)之类的工具检索对象并更新其属性 EntityKey是id属性的一个单独的东西,其他一些东西在幕后进行。您新创建的对象缺少这些内容,这就是问题的根源 模式有点像(不是C#guy,所以请原谅语法):
关键的区别在于,新检索的对象已正确设置EntityKey all。您可以有效地使用id属性来检测新的/现有的对象,但EntityKey不仅仅是该属性。因为您使用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();
}
使用(bisenties context=new bisenties())
{
if(adCategoryFilter.Id<1)
AddObject(adCategoryFilter);
否则{
var stub=newadcategoryfilters{Id=adCategoryFilter.Id};
context.AdCategoryFilters.Attach(存根);
context.adCategoryFilter.ApplyCurrentValues(adCategoryFilter);
}
SaveChanges();
}
这被称为存根技术。
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
简而言之,您创建了一个新实体,其实体键与您尝试更新的实体相同(在您的情况下,实体键为“Id”)
然后“附加”此存根(因此它由EF内部图跟踪),然后使用要更新的实体覆盖此存根上的值,然后保存更改
我不能使用UpdateModel,因为我有一个多层体系结构,并且使用POCO、自定义视图模型等,所以我在我的服务/存储库上创建了一个自定义的“UpdateModel”方法,它执行上述(更复杂的)版本
另外,请尽量不要在ASP.NET MVC中使用“if Id<1,这是一个添加”-如果您忘记在视图上绑定Id,它将作为0传递,因此即使您可以执行更新,您上面的代码也会尝试执行添加
相反,要更加明确-为添加/更新提供单独的操作方法
嗯。谢谢,听起来不错。但是MVC中的UpdateModel和AutoMapper()之间有什么区别呢?不确定,我还没有看过它们的内部结构。我认为它们都使用反射,并且非常相似,实际上我使用自己的自定义反射,在自定义反射中我显式地标记要在元数据中更新的属性。这两种方法所做的基本上都是让您不用为每个属性反复编写origObject.Property=viewModel.Property——您可以这样做,它也同样有效。
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();
}