实体数据模型:外键巧用

[原文作者]:Yang Cao

[原文链接]:Entity Data Model: working with foreign key when you don’t have it

        概念模型中是否包含FK(外键)一列争议已久,因此Visual Studio 2010在创建实体数据模型的向导中添加了一个复选框。这样,是否使用外键由开发者自己去决定。昨天我做了一些有趣的事情,发现了外键在下面介绍的情况下有着突出的作用。

我的应用程序十分简单:将A中与Order相关的客户移到B中。

image

        如果FK(CustomerID)在Order这个 实体当中存在,我要做的,仅仅是针对外键建立一个查找绑定,然后调用dataContext.SaveChanges()。如何使用拖拽的方法在组合框组件上创建一个查找绑定?首先,将FK列(本例中Order实体的CustomerID列)拖拽到窗体上,与此同时将会生成一个组合框,然后将与之相关的查询表(Customer实体)拖拽到刚才生成的组合框上,这样之后,SelectedValue、SelectedValuePath,、ItemsSource和 DisplayMemeberPath等属性就会自动设置。

如果实体中并不存在FK列,事情将变得稍微麻烦一点。

Orders绑定到DataGrid

image

这个步骤很简单,只需要将Orders节点拖拽到WPF设计器上。

针对组合框创建一个查询绑定

        因为在这个模型中,我没有FK列,也就是说在Order实体中不存在CustomerID属性。为了创建一个查询绑定,我需要将Orders中的Customer实体展开,将CustomerID绑定到一个组合框上。

clip_image002

        当把这个节点拖拽到WPF设计器上之后,我就创建 了一个复合绑定。为了将它转换成一个查询绑定,我会将这个新创建的组合框链接到查询表上。为了达到这个目的,我们首先将Customers节点(上图中标记为2)拖拽到组合框上,你会注意到在这个过程中你的鼠标将会由“+”变成一个箭头,这表明我们并没有创建新的控件,而是使已有的控件根据拖拽上来的资源进行更新。

创建一个按钮保存修改

然后我会添加一个按钮“Update Customer”,在它的点击处理事件当中,我需要找到当前选中的order,获取新的CustomerID去替换之前的FK的值,保存修改:

Order currentOrder = (Order)ordersViewSource.View.CurrentItem;

string customerID = customerIDComboBox.SelectedValue.ToString();

currentOrder.CustomerReference.EntityKey.EntityKeyValues[0].Value = customerID;

northwindEntities.SaveChanges();

为了简化代码,在MainWindow类中,我将DataContext(northwindEntities)和CollectionViewSource(ordersViewSource)设置成属性。我需要在Order下,找到CustomerReference并且设置EntityKeyValue

F5

调试程序,一开始一切都进行的很顺利,但是当我在组合框中由一个customer切换到另一个时,弹出一个异常—- InvalidOperationException:CustomerID是对象键值信息的一部分,不允许修改。尽管我成功的创建了查询绑定,但是却不能修改它的值,因为SelectedValue不是Order的外键,而是Customer的主键!

这个异常提醒我,组合框应该绑定为OneWay模式。我在XAML文件中找到组合框,更新了SelectedValue的绑定模式:

SelectedValue="{Binding Path=Customer.CustomerID,Mode=OneWay}"

再次F5

现在改变组合框中的选项不会再弹出刚才的异常。我点击“Update Customer”按钮继续测试,出现另一个异常:EntityKey一经设定,不能再做修改。我就不信办不到,我到网上开始搜索,然后发现,尽管EntityKey无法重新设置,但是实体的键值是可以的。现在我们对FK的值进行以下修改:

currentOrder.CustomerReference.EntityKey = new System.Data.EntityKey(currentOrder.CustomerReference.EntityKey.EntityContainerName+"."+currentOrder.CustomerReference.EntityKey.EntitySetName,"CustomerID", customerID);

如果你拥有的是一个复合键,你可以使用KeyValuePair。想要了解更多,请看这里

完成以上所有步骤,我的程序总算如所期望的那样工作了。也许你会问,为什么你不简单的在设计中包含外键,以避免这些不必要的额外代码和可能出现的异常?那我会告诉你,如我之前所说的,有些设计者,在概念模型中,并不倾向于包含FK列,因为FK是关系数据库中的概念。另一个原因是,包含FK的功能在Visual Studio 2010里新添加的表中才开始得应用,如果你有一个已存在的实体数据模型,那么你始终得习惯没有FK的生活。

如果你有什么想法或是问题,我将会很高兴与你共同讨论。

谢谢!

《实体数据模型:外键巧用》有18个想法

  1. Thank you for posting this, It’s just what I was browsing on bing. I’d very much rather hear opinions from an individual, rather than a corporate web page, that’s why I like blogs so much. Thanks!. Just bookmarked your site! I’ll be back to check out your future postings. A shapely Added Agreeable.

  2. Thanks! Will probably be nice to anyone who usess it, including myself. Sustain the nice work for positive i’ll take a look at extra posts.. My sis advised me about your site and how great it is. She’s right, I’m really impressed with the writing and slick design. awesome 😉 ;).

  3. I Really enjoyed your blog. I just bookmarked it. I am a regular visitor of your website I will share It with Yep. I lurk there often. You guys have a wonderful blog. Keep up the good work.. This is probably one of the best mentions of this topic I’ve seen in quite a while. It’s obvious that your knowledge of the subject is deep and this made for a very interesting read. pleasing awesome terrific.

  4. TY a ton for posting, it was very informative and helped tons.. This is probably one of the best mentions of this topic I’ve seen in quite a while. It’s obvious that your knowledge of the subject is deep and this made for a very interesting read. pleasing fantastic tremendous.

  5. It’s hard to find knowledgeable individuals on this matter, but you sound like you already know what you’re talking about! Thanks. I Really enjoyed your blog. I just bookmarked it. I am a regular visitor of your website I will share It with Yep. I lurk there often. You guys have a wonderful blog. Keep up the good work. 🙂 fantastic terrific.

发表评论