怎么用FK设置收藏属性?我有一个业务和类别模型。每个企业通过暴露的集合拥有许多类别(类别忽略业务实体)。现在这是我的控制器操作:[HttpPost][ValidateAntiForgeryToken]privateActionResultSave(Businessbusiness){//Context是一个延迟加载的属性,它返回对DbContext的引用//它的处理在控制器的Dispose覆盖中得到处理.foreach(varcategoryinbusiness.Categories)Context.Categories.Attach(category);如果(business.BusinessId>0)Context.Business.Attach(business);否则Context.Businesses.Add(business);语境。保存更改();返回RedirectToAction("索引");现在有几个business.Categories的CategoryId设置为现有的Category(缺少Category的Title属性)。单击SaveChanges并从服务器重新加载业务后,类别不存在。所以我的问题是使用给定数组的现有CategoryId设置Business.Categories的正确方法是什么。但是,在创建新业务时,调用SaveChanges时抛出以下DbUpdateException:保存关系的外键属性未公开的实体时发生错误。EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地处理保存时的异常。有关详细信息,请参阅内部异常。内部异常(OptimisticConcurrencyException):存储更新、插入或删除语句会影响意外的行数(0)。实体在加载后可能已被修改或删除。刷新ObjectStateManager条目。更新答案后,这里是更新的代码:varstoreBusiness=IncludeChildren().SingleOrDefault(b=>b.BusinessId==business.BusinessId);varentry=Context.Entry(storeBusiness);entry.CurrentValues.SetValues(业务);//storeBusiness.Categories.Clear();foreach(varcategoryinbusiness.Categories){Context.Categories.Attach(category);storeBusiness.Categories.Add(类别);}调用SaveChanges,我得到以下DbUpdateException:SavenotAnerroroccurredwhileexposingentitieswhichrelationship'sforeignkeyproperties.EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地处理保存时的异常。有关详细信息,请参阅内部异常。下面是业务/类模型的外观:publicclassBusiness{publicintBusinessId{get;放;}[Required][StringLength(64)][Display(Name="Companyname")]publicstringCompanyName{get;放;}publicvirtualBusinessTypeBusinessType{get;放;私人ICollection_Categories;publicvirtualICollectionCategories{get{return_Categories??(_Categories=newHashSet());}设置{_Categories=值;}}私有ICollection_Branches;publicvirtualICollectionBranches{get{return_Branches??(_Branches=newHashSet());}设置{_Branches=值;}}}publicclassCategory{[Key]publicintCategoryId{get;放;}[唯一][必需][MaxLength(32)]publicstringTitle{get;放;}公共字符串描述{得到;放;公共诠释?ParentCategoryId{得到;放;}[Display(Name="Parentcategory")][ForeignKey("ParentCategoryId")]publicvirtualCategoryParent{get;放;私人ICollection_Children;公共虚拟ICollection儿童{得到{返回_Children??(_Children=newHashSet());}设置{_Children=值;}}}再次说明,我附加到现有/新业务的类别I已经存在于数据库中并且有一个ID,这是我用来附加它的ID。我将这两种情况——更新现有业务和添加新业务——分开,因为你提到的两个问题有不同的原因。更新现有业务实体这就是您示例中的if情况(if(business.BusinessId>0))。显然这里没有做任何事情,更改也没有存储到数据库中,因为您只是附加了Category对象和Business实体,然后调用SaveChanges。追加意味着实体被添加到处于未更改状态的上下文中,因为处于该状态的实体EF根本不会向数据库发送任何命令。如果您正在更新分离的对象图-在您的情况下业务加上类别实体的集合-您通常会遇到这样的问题,即集合项目可能已从集合中删除并且项目可能已添加-与当前状态相比数据库中的商店。集合项和父实体Business的属性也可能已被修改。除非您在分离对象图时手动跟踪所有更改——即EF本身无法跟踪更改——这在Web应用程序中很难,因为您必须在浏览器UI中执行此操作,这是您在整体上进行正确更新的唯一机会对象图将其与数据库中的当前状态进行比较,然后将对象置于正确的状态:添加、删除和修改(其中一些状态可能为未更改)。所以这个过程是从数据库中加载业务及其当前类别,然后将分离图的更改合并到加载的(=附加的)图中。它可能看起来像这样:privateActionResultSave(Businessbusiness){if(business.BusinessId>0)//=businessexists{varbusinessInDb=Context.Businesses.Include(b=>b.Categories).Single(b=>b.BusinessId==business.BusinessId);//更新父属性(仅标量属性)Context.Entry(businessInDb).CurrentValues.SetValues(business);//如果关系存在于数据库中,则删除与类别的关系//但已在UI中删除CategoryId==categoryInDb.CategoryId))businessInDb.Categories.Remove(categoryInDb);}//如果关系不存在则将关系添加到类别//在数据库中但已添加到UIforeach(varcategoryinbusiness.Categories){varcategoryInDb=businessInDb.Categories.SingleOrDefault(c=>c.CategoryId==category.CategoryId)如果(categoryInDb==null){Context.Categories.Attach(categ论);businessInDb.Categories.Add(类别);}//这里没有其他情况,因为我假设类别不能//已经在UI中被修改,否则其他情况将是://else//Context.Entry(categoryInDb).CurrentValues.SetValues(类别);}}else{//见下文}Context.SaveChanges();返回RedirectToAction("索引");}添加一个新的业务实体你添加一个新的业务和它的相关类别没错。只需将所有类别作为现有实体附加到上下文,并将新业务添加到上下文:foreach(varcategoryinbusiness.Categories)Context.Categories.Attach(category);上下文.业务.添加(业务);上下文.SaveChanges();如果您附加的所有类别确实具有数据库中存在的键值,这应该无一例外地工作。您的异常意味着至少一个类别具有无效的键值(即它不存在于数据库中)。也许它同时从数据库中删除,或者因为它没有从WebUI正确发回。如果它是一个独立的关联——没有CategoryFK属性BusinessId的关联——你确实会得到这个OptimisticConcurrencyException。(EF似乎在这里假设该类别已被其他用户从数据库中删除。)如果它是外键关联-这是一个在类别上具有FK属性BusinessId的关联-您将获得有关外键约束的异常违规行为。如果你想避免这个异常-如果它实际上是因为另一个用户删除了一个类别,而不是因为类别是空的/0因为它没有被发送回服务器(用隐藏的输入字段修复它)-你最好最好通过CategoryId(Find)从数据库加载类别而不是附加它们,如果不存在则忽略它并将其从business.Categories集合中删除(或重定向到错误页面以通知用户或类似的东西)。我也有这个例外。我的问题是ADOEntityFramework没有设置添加对象的主键。这导致了无法为添加到数据库中的对象设置外键的问题。我通过确保主键由数据库本身设置来解决这个问题。如果您使用的是SQLServer,则可以通过将IDENTITY关键字和列声明添加到CREATETABLE语句来实现。希望这有助于我在试图设置超出其MaxLength属性的字段上获得此异常。该字段还具有Required属性。我正在攻击Oracle后端数据库。直到我增加了长度,我终于从底层数据库引擎那里得到了一个描述性的错误信息,说长度太长了。我怀疑与外键相关的错误消息含糊地表示并非所有关系都可以更新,因为其中一个插入失败并且其键未更新。以上是C#学习教程:如何使用FK设置集合属性?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
