实体框架 EntityKey / 外键问题

7
作为表单提交的结果,我正在尝试保存一个新的品牌记录。在我的视图中,性别是一个下拉列表,返回一个整数,这个整数是从ViewData("gender")中填充的。
我已经设置了以下链接:
gID = CInt(Request.Form("Gender"))
Brand.GenderReference.EntityKey = New EntityKey("DB_ENTITIES.Gender", "Id", gID)
TryUpdateModel(Brand)
DB.SaveChanges()

这会导致以下错误发生。
Entities in 'DB_ENTITIES.Brand' participate in the 'FK_Brand_Gender' relationship. 0 related 'Gender' were found. 1 'Gender' is expected.

请问有人能用通俗易懂的英语解释一下这些参数吗?我也尝试过将DB.Gender作为第一个参数,但没有成功。

3个回答

18

不要创建 EntityKey,而是创建一个 Gender 对象的存根(抱歉我不太懂 VB,所以这里给出 C# 的示例):

Gender g = new Gender{ID = Int32.Parse(Request.Form("Gender"))};

然后你将性别附加到相应的EntitySet上(从DB获取性别实体的属性名称如下所示):

DB.AttachTo("Genders",g);

这将使得数据库中的Gender处于未更改状态,而无需进行数据库查询即可在ObjectContext中建立正常关系。

brand.Gender = g;
DB.AddToBrand(brand);
DB.SaveChanges();

就是这样了。没有必要与实体键 EntityKeys 纠缠。

希望这可以帮到你。

Alex


谢谢您的回复,Alex - 现在已经解决了:具有相同键的对象已存在于ObjectStateManager中。 ObjectStateManager无法跟踪具有相同键的多个对象。 - Squiggs.
Paul,你是如何解决“多个具有相同键的对象”问题的?我也遇到了同样的问题。 - Picflight
2
在将某物附加到上下文之前,您应该使用LINQ to Objects检查ObjectStateManager,以确保相同的对象尚未存在。 - Alex James

1
你需要的是一个Brand和Gender的实例,然后将Brand.Gender设置为Gender的实例。这样你就可以顺利保存了。

这不需要回到我的数据库吗?肯定是视图返回了一个可以关联起来的ID。 - Squiggs.
这取决于对象是否已经在上下文中,如果是,则不需要访问数据库。可以使用Alex James的代码(它几乎与我所写的相同)。 - Jonathan van de Veen

0

好的,这是我想到的替代updateModel的方法。使用updateModel似乎存在问题/潜在的安全风险,因为在提交时可能会添加其他字段。可以通过trygetObjectByKey实例化Gender的新实例。目前这种方法可行。如果有其他关于如何更新Gender属性对象的建议,请告诉我。

Dim cID As Integer
cID = CInt(Request.Form("Gender"))
Dim key As New EntityKey(DB.DefaultContainerName() & ".Gender", "ID", cID)

Dim objGenderDS As New Gender
'Bring back the Gender object.
If DB.TryGetObjectByKey(key, objGenderDS) Then
Brand.GenderReference.EntityKey = key
Brand.Gender = objGenderDS
DB.AddToBrand(Brand)
DB.SaveChanges()
Else
End If

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接