数据点

实体框架设计器在 Visual Studio 2012 中功能增强

Julie Lerman

 

Julie Lerman我必须承认,我非常热衷使用“代码优先”来生成实体框架可以使用的域模型。我不太关注 EDMX 模型,您可以使用实体框架设计器通过“数据库优先”或“模型优先”模型来生成它。(请参见我的 2011 年 5 月专栏“揭密实体框架策略: 模型创建工作流”[msdn.microsoft.com/magazine/hh148150],了解“代码优先”、“模型优先”和“数据库优先”之间的区别。)

但是在过去我一直依赖设计器工作,要作出改变是否因为年纪过大而力不从心呢?我年纪太大,习惯使用实体框架,但是您现在必须处理原始 XML,因为没有设计器了。这是真的。这是第一版推出之前使用早期测试版遇到的情形。因此,将设计器集成到 Visual Studio 2008 是件大好事。Microsoft 做了一件有意义的工作,即使它始终可以轻松找到完善自己、改进不足之处的方法。在 Visual Studio 2010 中,我们获得了“模型优先”支持并在设计器中新增了其他一些有用的功能,如复数化和外键支持。

现在,Visual Studio 2012 提供一个功能更强大的设计器。它有两项重大更改,同时还进行了轻微调整,使得我的工作更加轻松,心情愉快,希望对您也是如此。

1, 2, 3, 颜色!

您可能已听说一项显著的改进 - 可以在设计器中向实体添加颜色。这个功能使用起来很简单。您可以选择一个或多个实体,然后在属性窗口中选择这些实体的颜色,如图 1 中所示。颜色便于以直观方式标记实体。当您打开模型时,可以轻松看到实体在模型中与其他实体的相对关系。即使在小模型(如图 2 中所示)中,此功能也非常有用。

Changing the Color of Entities
图 1 更改实体的颜色

Easily Visualize Entity Groupings with Color
图 2 使用颜色轻松可视化实体组

使用关系图组织

人们一直在争论多少实体对于模型而言过多。在我看来,如果单个模型中包含 20 或 30 个以上的实体,则这个模型从直观性和实际操作角度来说都将无法管理。我的意思是,一次很难查看所有实体信息,并且,当我要在设计器中使用一个或多个实体时非常麻烦。我经常使用设计器的模型浏览器来帮助在设计图面上查找一个实体。如果模型巨大(包含数百个实体 - 我永远不会尝试),您可能遇到设计时和运行时性能问题。(请参见 Microsoft 数据开发人员中心主题“Entity Framework 5 的性能注意事项”,网址为 bit.ly/OZTiUL。) 一些第三方 EDMX 设计器通过采用不同方法来处理大型模型,可以避免此问题。我偏好创建小模型以供应用程序使用,但有时可能并不适用。可以在设计器中管理单个模型中的多个实体,这一点很重要。

新设计器通过提供关系图这个经常请求的功能,帮助开发人员解决此问题。使用模型关系图,您可以创建说明模型所含信息的不同设计时视图。您可能需要一个显示整个模型的视图(如图 2 中所示),然后使用其他关系图来表示将实体分组的不同方式。设计器提供了很多创建关系图的方法,但是请注意那些移动而非复制实体的功能。

例如,我可能需要这样的关系图:在设计时重点处理客户管理时仅显示我需要的实体。在此特定模型中,这可能是 Customer 和 ShippingAddresses。您可以通过几种方法实现此目的。其中一种方法是:选择这些实体,右键单击它们,然后从上下文菜单中选择“移到新关系图”选项。这将创建一个只包含这两个实体的新关系图,如图 3 中所示。但是因为我使用了“移动”选项,那两个实体已从主关系图中删除。如果您要保留总体模型的单个关系图,请务必小心。我希望关系图不反映模型架构情况,您可以在其中查看导航属性(例如 Customer.Orders),即使在该特定关系图中不显示 Orders 实体。

Diagram Created Using the Move to New Diagram Feature
图 3 使用“移到新关系图”功能创建的关系图

您还可以通过设计器的模型浏览器创建和管理关系图,如图 4 中所示。从模型浏览器,您可以选择要查看的关系图,以及添加和删除关系图。您还可以将实体从模型(例如在 Company­DatabaseModel 的“实体类型”部分)拖到关系图图面。因此,如果我希望将 Customer 和 ShippingAddress 保留在关系图 1 中,可以从模型浏览器创建一个新关系图,然后将 Customer 和 ShippingAddress 拖到该图面上。

Manage Diagrams from the Model Browser
图 4 从模型浏览器管理关系图

此外,您可以将实体从一个关系图复制并粘贴到另一个关系图并附带所有相关的关联信息。

请记住,关系图是设计时视图,它们并不全面定义模型。您始终可以在模型浏览器中查看完整模型。因此,将实体从一个关系图复制到另一个关系图对您的模型或应用程序没有影响。但是它们不是只读视图。您仍可以在这些关系图中设计模型和实体,这些更改将影响基础模型。对于关系图中的任意实体,我还建议您右键单击该实体并选择“包含相关的”选项以包含直接相关的所有实体。

默认代码生成: POCO 和 DbContext

另一项使我感到高兴的变化是,我首次发现创建新的实体数据模型的向导目前在默认情况下使用 Entity Framework 5 DbContext T4 模板。自从发布 Entity Framework 4.1(它包含“代码优先”和 DbContext API)后,EF 小组建议开发人员使用 DbContext 和简单传统的 CLR 对象 (POCO) 类替代 .NET 4 ObjectContext 和从 EntityObject 继承的类来创建新项目。但 Visual Studio 2010 使用默认为 ObjectContext 和 Entity­Objects 的代码生成模板。开发人员自己选择是否安装 EntityFramework.dll NuGet 包和切换 EDMX 以使用 DbContext 模板。这意味着您必须了解新指南并执行相应操作。

目前,设计器默认使用 EF 5.x DbContext 生成器模板,创建一个 DbContext 类和 POCO,这些对象比以前的类型更易于在您的应用程序中使用。向导还将包含对 EntityFramework.dll 的引用,后者随 Visual Studio 2012 一起安装到您的计算机,因此您甚至不需要 Internet 连接。

您可以轻松恢复到使用 ObjectContext。请查看 Microsoft 数据开发人员中心主题“恢复到 ObjectContext 代码生成”,网址为 bit.ly/OFjcLa

定义枚举类型

Microsoft .NET Framework 4.5 提供对实体框架的枚举支持。您可以将枚举用于 EDMX 和“代码优先”。使用 EDMX 时,您需要使模型识别枚举类型,以便实体框架知道如何转换它们来将它们映射到数据库类型。使用实体框架设计器,您可以轻松执行此操作。

如果您对数据库执行逆向工程以得到 EDMX 模型,向导将数据库列解释为 .NET 类型。您然后必须定义自己的枚举类型并修补属性。让我们快速看一下该过程。

我的模型中的 Return 实体具有一个名为 Reason 的属性,它映射为一个整数。我想将 Reason 表示为一个枚举而不是创建一个额外数据库表和实体,我可以在设计器中进行此更改。右键单击设计器背景,在“新增”下,您将看到“枚举类型”是列表中的新项。选择它以打开枚举类型向导,在此您可以定义枚举,如我在图 5 中所做的那样。枚举类型在设计器图面上不可见,但是您始终可以在模型浏览器中对其进行操作(查看、编辑或删除)。

Defining an Enum Type
图 5 定义枚举类型

既然模型可以识别此枚举类型,我可以在实体中使用它。我将返回到 Return 实体并编辑 Properties of the Reason 属性。类型最初为 Int32。新的枚举类型显示在“类型”下拉列表中,如图 6 中所示,但是您必须向下滚动到底部以查找它。选择该类型后,无论您是在编写 LINQ 查询、检索数据还是更新数据,实体框架都知道如何将枚举转换为一个数据库值。

Selecting a New Enum Type
图 6 选择新的枚举类型

例如,以下是一个对 ReturnReason 枚举进行筛选的 LINQ 查询:

var returns = context.Returns.Where(
  r => r.Reason == ReturnReason.Broken).ToList();

在数据库中执行该查询时,将 Broken 枚举转换为枚举值 3,如此 TSQL 位中所示:

WHERE 3 =  CAST( [Extent1].[Reason] AS int)

您可能注意到图 5 中的“设置标志”属性和“引用外部类型”复选框。 EF 支持按位枚举,允许您在设置或查询数据时组合枚举。 “设置标志”指定将按位枚举。 EF 小组的 Pawel Kadluczka 发布过一篇很好的博客文章“使用 Entity Framework 5 中的现有枚举类型”(bit.ly/QIUz6y),该文章详细介绍了“引用外部类型”复选框的功能。

请注意撰写本文时,WCF Data Services 5 不识别枚举类型。 请查看 WCF Data Services 小组博客(网址为 blogs.msdn.com/astoriateam),了解有关此问题的更多信息。

成批导入存储过程

图 7 显示我很久以前就希望拥有的另一个功能,我很高兴在 Visual Studio 2012 中的实体数据模型向导中看到它。 Visual Studio 2010 中的设计器允许您将存储过程映射到复杂类型,但是您不必一次一个存储过程来进行操作。 该功能仍提供,但是现在有了快捷方式。 当您创建“数据库优先”模型时,可以让向导同时从存储过程创建函数,向导将创建函数将映射到的所需的复杂类型。

Creating Function Imports from Stored Procedures
图 7 从存储过程创建函数导入

图 8 显示新的函数导入以及模型浏览器中的相关复杂类型。 我通常不喜欢使用向导创建的默认名称。 但是使用向导为我创建这些资产然后编辑名称与我自己逐一创建它们相比,前者的速度更快。

The New Function Imports
图 8 新的函数导入

如果您要从一些存储过程创建函数导入,但从其他存储过程创建实体映射(即在添加新联系人并调用 SaveChanges 的任何时候使用 Insert­Contact),建议您采用两个步骤执行此操作。 在第一步中,您只选择要作为函数导入的存储过程及其相关的复杂类型。 然后使用“从数据库更新模型”功能,您可以选择要用于映射的过程并确保未在第二步中选中“导入所选存储过程…”复选框。

TVF 和地理支持

EF5 支持映射到表值函数 (TVF) 和空间数据(如 SqlGeography 和 SqlGeometry),设计器也支持这些功能。 您可以通过查看与 TVF 和空间类型有关的演练(网址分别为 bit.ly/QCppJJbit.ly/VdbEUP),了解如何通过设计器来利用这些映射。

与枚举支持一样,请注意,WCF Data Services 5 不支持您可以在 EF5 模型中定义的地理类型。

细微的改进

还有很多对实体框架设计器的细微改进,它们累加起来会显著提高性能,使我们可以更加轻松地使用设计器。

移动属性:在设计器中,您可以重新组织实体中的属性,以便以所需的顺序列出它们。 在早期版本中,只能通过直接编辑 XML 来移动属性。

表选择中的架构:创建“数据库优先”模型或从数据库更新模型时,现在按架构名称组织表、视图和其他数据库对象。 如果您在按架构组织数据库对象时遇到问题,将会从中受益,因为现在可以更轻松查找对象。 您可以轻松除去不属于域的对象,如图 9 中的 dbo 架构表。

Grouping Database Objects by Schema Name
图 9 按架构名称对数据库对象分组

模型更新中反映的列方面更改:“从数据库更新模型向导”现在接受对列方面(Scale、Precision、MaxLength、Nullable、Unicode 和 FixedLength)的更改并将它们应用到模型中的相关属性。 这会给很多开发人员带来便利。 但是,当您更改列类型时仍必须修复损坏的映射。 MSDN 上有一个文档详细介绍了这些影响,标题为“通过更新模型向导对 .edmx 文件所做的更改”(bit.ly/PTOwKB)。 撰写本文时,介绍列更改的章节尚未包含有关方面的新详细信息。

突出显示选定内容上的相关实体:这是另一个可帮助您以直观方式理解模型的小改进 - 当您在设计器中选择一个实体或关联时,相关实体也将突出显示。

有关上下文菜单上的“重构”项的注释:Visual Studio 2012 的预发行版本包含一个设计器功能,如果您重命名实体或属性,该功能将重构相关代码。 该功能未集成到 Visual Studio 2012 的最终版本中,但是设计器中有一些可能引起混乱的项目。 上下文菜单有一个“重构”项,它具有子菜单“重命名”。 如果您从“重构”菜单中选择“重命名”,将弹出一个窗口,指示不更改任何代码。 由于将不发生重构,该窗口将不列出任何内容。

稳定的改进

尽管本文侧重介绍 Visual Studio 2012 中针对实体框架设计器的新功能,您不应忽视 EF5 中的其他一些增强功能。 最显著的增强是有关新的自动编译的查询如何改进基础性能的。 您可以阅读小组博客文章“先睹为快: Entity Framework 5.0 性能改进”(bit.ly/PLWu5l),了解这方面的信息。 无论您是使用实体框架设计器生成模型还是利用“代码优先”设计模型,EF5 都会给您带来很多惊喜。

Julie Lerman是 Microsoft MVP、.NET 导师和顾问,住在佛蒙特州的山区。 您可以在全球的用户组和会议中看到她对数据访问和其他 Microsoft .NET 主题的演示。 她是《Programming Entity Framework》(2010) 以及“代码优先”版 (2011) 和 DbContext 版 (2012)(均出自 O’Reilly Media)的作者,博客网址为 thedatafarm.com/blog。 请关注她的 Twitter:twitter.com/julielerman

衷心感谢以下技术专家对本文的审阅: Lawrence Jones