我的asp.net MVC应用程序中有一个向导,它基于this SoG - RESTFUL wizard guide构建。
为了解这个问题,我先解释下面的情况。为此,我将使用虚拟情况,我们尝试创建一个具有地址的人。再说一次,这只是一个虚拟的情况!
情况
开始时,使用向导创建和保存的对象(人物)将创建为空白对象(人物),并在向导“阶段”期间填充。在各种向导步骤之间,person对象存储在SESSION中并使用键检索。该对象与子对象有关系。例如,一个地址。可以使用向导中的下拉菜单从数据库中检索此地址 ,也可以在向导本身中创建。这意味着在创建时我将创建一个空地址对象,因此我们进行了以下初始化:
Persons p = new Persons();
p.Addressess = new Addressess()
此对象传递给FormViewModel并在向导表单中使用。在这里,我有一个下拉菜单,可以选择:(1)*为person创建新地址,使用通常的方式(TryUpdateModel())和(2)“地址x”填充传递的空地址对象,地址可从您的数据库中选择。
在下拉列表中选择一个地址将在控制器POST方法中从DB检索此对象并将其耦合到person.Addresses。在代码中:
p.Addresses = repository.GetContactByID(id);
问题
在浏览向导页面时,一切正常。当我调用savechanges()时会出现问题。在最终概述中,正确显示要添加的完整对象(人员信息+选择/传递的地址信息),同时将空地址保存到数据库中。
repository.SaveChanges();
这会尝试向DB添加一个空的地址,这会引入一个ModelState错误,因为地址有一些不可为空的对象,而这些空值没有为空对象设置。
**我目前的想法** 我当前的想法是,当我第一次将它连接到person.Addresses时,在空白对象的开始时创建的空对象以某种方式被置于添加状态(objectcontext)。情况可能如此吗?做我想要的正确方法是什么?我可以手动删除对象上下文_addedEntityStore中的内容吗?
其他信息
在下拉列表中选择一个地址将强制一个form.submit到POST控制器方法,然后它会重新加载带有更新的选择信息和输入字段的表单对于新地址(如果需要新地址)设置为“已禁用”,因此您只能看到信息但无法编辑现有地址。
此外,仅使用一个objectContext ,它保存在SESSION中。
答案 0 :(得分:1)
当你第一次创建p.Addressess
对象时,你不能只将Persons
留空,只有在向导中选择它时才添加新地址?
(而BTW为什么奇数复数?他们有一个地址还是几个?)
您将遇到的另一个问题是您将在一个上下文中加载现有地址并将它们保存在另一个上下文中(假设您正在使用每个请求方法的上下文) - 您需要从一个上下文中分离现有地址加载并将它们附加到用于在向导结束时保存Person的上下文。
在Session状态中包含单独的AddressNew
和AddressExisting
对象可能更容易(一个或另一个为null)。最后,如果存在AddressNew
,请将其添加到Person
并保存更改。如果存在AddressExisting
,请将其附加到上下文,将其添加到Person
并保存更改。
答案 1 :(得分:0)
虽然Hightechrider对于每个工作单元都使用对象上下文是正确的,但我发布了我现在使用的简单解决方案。当你以某种方式(强迫,选择,等等)将对象上下文存储在SESSION中时,只需调用以下内容即可解决上述问题:
repository.Detach(person.Addresses)
将旧对象从上下文中分离(尚未保存到DB)。分离后,附加要链接到的新对象。
person.Addresses = repository.GetAddressByID(id);
// or
person.Addresses = new Addresses();
虽然如果您需要这样做并且有时间和力量,我建议您重写您的向导:)。
修改强>
请注意,Detach仅分离提供的对象,而不是其相关对象(!)。