Entity Framework 学习总结之二:数据访问区别
解释 EntityClient 和对象服务之间的差异,并介绍将 LINQ 和 EntitySQL 与这些服务一起使用的意义。可使用 LINQ 获取实体时为什么要使用实体 SQL?
介绍可用于与 EDM 进行交互的三种主要技术:
· 使用 EntityClient 提供程序编写 EntitySQL 查询
· 使用对象服务编写 EntitySQL 查询
· 使用对象服务编写 LINQ 查询
以上每种技术都拥有共同的特征;例如,都直接或间接使用 EntityClient 提供程序。但是,它们产生的结果以及获得这些结果的方式却有所不同。
EntityClient 提供程序具有一系列对象,如果了解 ADO.NET 对象模型,则您应该熟悉这些对象。EntityConnection 用于连接到 EDM,EntityCommand 用于针对 EDM 发出查询,而命令的结果则通过 DbDataReader 返回。无论是通过对象服务直接还是间接使用 EntityClient,EntityClient 最终都会发出查询并返回结果。
这使得问题再次摆上桌面,为什么有 LINQ 却要使用 EntitySQL?答案在于每种技术的优缺点。
EntityClient + EntitySQL
深入分析:实体框架数据加载
许多对象关系映射框架都支持以下两种众所周知的行为,它们有助于编写短期“探测”代码、改进应用程序使用数据库的次数和数据传输量:
· 预先加载:每次程序需要操作一组相关对象时,都会在一个先期请求中从数据库冻结整个图。
· 延迟加载:当程序导航连接对象图的属性时自动从数据库加载数据,此时可能多次访问存储库,但仅加载必需的项目。
为遵循“无隐藏网络往返操作”原则,实体框架放弃了自动化延迟加载。遍历由代码生成的类所组成的图这一操作永远不会针对存储库触发查询。实体框架代之以要求用户代码在使用之前明确冻结所有对象。
可随时加载,但在每次要执行加载时需针对引用或集合调用称为 Load 的方法。实际上,通过干涉代码生成过程或通过编写自己的类,仍可实现隐式延迟加载。但是,更常见的方法是延迟加载而非仅隐藏往返操作。您必须了解,每次程序使用延迟加载时,都容易得到一个包含不一致数据的图。并且,如果程序不及时刷新已加载的数据,图中的数据就可能会失效。
通过使用 EntityClient API 编写代码,可最精细地控制这三种技术。可创建 EntityConnection 来连接 EDM,以 EntitySQL 编写一个查询并使用 EntityCommand 执行该查询,然后通过 DbDataReader 返回结果。此技术要精简一些,省去了 LINQ 和对象服务提供的一些语法修饰。
EntitySQL 最大的优点是其灵活性。基于字符串的语法有助于轻松地构建动态查询。如果需要创建临时查询,它将非常有用。但是,这种灵活和精简也使得只能通过 DbDataReader 返回结果。无法使用 EntityClient 和 EntitySQL 从 EDM 返回纯实体。DbDataReader 可供检索并用于在满足 EntitySQL 查询的行集合中执行迭代。
对象服务 + EntitySQL
另一技术是使用对象服务并利用 EntitySQL 来执行查询。从而不再与 EntityClient 提供程序直接交互(尽管实际上它仍会与提供程序通信)。使用 ObjectContext 和 ObjectQuery<T> 来针对 EDM 发出查询。
此技术非常适合于发出临时查询(与第一种技术相同)。但是,它不是通过 DbDataReader 返回数据,将对象服务与 EntitySQL 一起使用时可从 EDM 返回实体。因此,可牢靠地提供以下优点:查询灵活且返回最佳实体。可使用此技术从 EDM 检索实体,然后使用 ObjectContext 中的 SaveChanges 方法来更新实体。
对象服务 + LINQ
将对象服务 LINQ 一起使用并不适合于临时查询,这一点与其他技术不同。
因此,为什么有 LINQ 却要使用实体 SQL?如果需要临时查询或希望创建比使用 LINQ 实现的查询更加灵活的查询,则应使用实体 SQL。否则,建议使用 LINQ 和对象服务,以便可受益于其强类型化以及返回实体和投影的功能。
如使用 LINQ 的强类型化语法,还可在设计时发现许多错误,不必等到运行应用程序时才发现。我非常喜欢这一功能——它使我可以一心一意编写代码,不必通过执行构建和运行来找出错误。
ObjectContext 的作用是什么? ObjectContext 是到对象服务的 EntityConnection 的通道。它通过底层 EntityConnection 提供对 EDM 的访问。例如,可通过 ObjectContext 访问实体,询问 ObjectContext 以找出有关对象状态的信息,以及使用 CreateQuery 方法创建 ObjectQuery<T> 查询。
ObjectContext 的另一目的是为对象提供获取数据库条目更新信息的方法。例如,可使用 ObjectContext 方法来将实体添加到 ObjectContext、删除实体、操作实体以及最终将实体更改保存到数据库(通过 SaveChanges 方法)。
结束语