Entity Framework 4中的一对一错误

3

我已经阅读了Entity Framework One-To-One Mapping Issues,但由于业务规则的不同,这不是重复内容。

有两个表,Invoices和Orders。

Invoices
-> InvoiceID (Primary, Auto Number)
Orders
-> OrderID (Primary, Auto Number)
-> InvoiceID (FK InvoiceID of Invoices Table)

现在的问题是,如果属性名不同,EF要求这个关联必须是一对多的关系。如果属性名相同,则可以作为派生类的目的,但是这里订单并不是派生类或发票。
每个购物车都会生成发票ID,但只有已支付的发票才会生成订单ID,所以每个订单都有发票ID,但不是每个订单都有相应的发票。
如果我为此创建一个单独的表,那么我就必须编写太多代码来完成它。是否有任何方法可以移除此限制,并让EF仍然处理我的模型。
然而,如果我按照以下方式更改模型,它就可以工作。
Invoices
-> InvoiceID (Primary, Auto Number)
Orders
-> OrderID (Auto Number)
-> InvoiceID (Primary, FK InvoiceID of Invoices Table)

但这是好的实践吗?因为按定义,订单表的InvoiceID肯定是唯一的,但我们将到处引用OrderID进行比较和许多其他引用。我知道我可以对属性建立索引,但我觉得这个设计并不完美。

一对一错误

1个回答

2
在这里最明显的解决方案是将EDM中发票和订单之间的1:*关联更改为1:1关联。但是,正如您所经历的那样,在模型中存在两个实体之间的外键关联时,映射将无法验证。唯一映射独特外键关联的方法是使用独立关联。这是与EF3.5中相同类型的关联,其中不支持外键。要将外键关联转换为独立关联,意味着需要从订单实体中删除InvoiceID外键并通过映射重新创建关联。要更改关联,您需要执行以下操作: 1. 从订单实体中删除InvoiceID外键属性。 2. 选择发票和订单之间的关联。 3. 在关联的属性窗口中,通过单击该属性旁边的省略号打开引用约束。 4. 通过单击删除按钮删除约束。 5. 右键单击设计器中的关联,然后从上下文菜单中选择表映射。 6. 在映射详细信息窗口中,单击元素以公开下拉列表。 7. 从下拉列表中选择订单。映射应自动填充。 8. 返回关联的属性窗口。 9. 对于当前具有* Orders集合值的“End2 Multiplicity”属性,请使用其下拉列表将该属性更改为1(Order中的One)。 10. 通过右键单击设计面并选择验证来验证模型。您会看到与此映射相关的错误消息已消失。 在应用程序中遇到此问题时,您必须决定外键标量(例如,Order.InvoiceID)或能够在通过外键(InvoiceID)连接时定义一个实体(发票)和另一个实体(订单)之间的1:1关联对于您的模型和应用程序逻辑更重要。好消息是,新的EF4.0惰性加载仍将与独立关联一起工作,只是不会公开外键。要获得它,您需要转到导航属性(发票)并像下面的代码一样读取其InvoiceID:
Order order = context.Orders.First();
int invoiceID = order.Invoice.InvoiceID;

或者您可以使用以下代码直接读取订单实体,而无需延迟加载或急切加载发票属性:

int invoiceID = order.InvoiceReference.EntityKey.EntityKeyValues[0].Value;

谢谢,一个快速的问题,如果我这样做,导航属性会起作用还是不起作用? - Akash Kava
没问题,当然可以工作。我更新了我的答案,向你展示了两种获取订单实体上隐藏的InvoiceId FK的方法。 - Morteza Manavi
1
我花了大约一个小时来尝试解决这种一对一映射的问题,非常感谢Morteza! - GONeale

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