Entity Framework 混合方法





3.00/5 (4投票s)
混合 DB-First 和 Code First 方法,以 EF 方式使用存储过程
引言:(为何混合?)
Code First 方法最适合大型系统,但它不支持 EF 方式的 SP。
使用 SP 可能只是一个选择,或者由于其他原因(如下文所述)而需要它。
如果您两者都需要(即 Code First 方法和 EF 方式的 SP 支持),那么我的解决方案是使用混合方法。
好的,但为何要写这篇详尽的文章?微软明确不建议使用 EF 的混合模式。因此,使用 EF 的混合模式需要一些技巧。
背景
为何混合,解释 (如果您已经信服,请跳过)
- 通常,对于大型项目,Code First 方法因其更高的灵活性、控制和数据库版本管理而更受欢迎。但是 EF(Code First / Design First)在以下方面表现不佳:
- 并发管理:EF 总是要求在将数据发布回数据库之前从数据库中获取数据,即每次“更新”/“插入”都会额外调用一次“SELECT”。当然,这是性能方面的考量。
- 更新/插入多条记录:即使您可以添加/更新多个实体而不调用数据库,并在最后调用“SaveChanges”将所有更改发布到数据库。它做了什么?它会获取最终的更改集,并逐个调用您的每项更改——每项更改调用一次数据库。
当然,这是性能方面的考量。
- Code First 方法需要大量编码才能开始。
- 上述问题的解决方案是,一个明智的架构师不会总是完全依赖 EF。为了保持设计和软件的灵活性以及最佳性能,他将有最好的选择:存储过程 (Stored-Procedures)。EF 6 对 SP 支持得很好,早期版本要么不支持,要么支持有限。
- 所以,让我们在 Code First 方法的同时使用 SP,但等等…
- 接下来呢?
- Code First 方法不支持 SP 映射(以及其他数据库对象映射,如查询视图、定义视图、表值函数、临时表等)。
- 这些映射在 Database First 方法中是支持的。
- 如果您想在 Code First 中映射 SP,那么也许可以做到,但工作量巨大。微软或其他开发者都没有记录或测试过这项工作。我太懒了。
- 在使用 Code First 方法调用 SP 时还有另一种可能性。这是一种低级别的调用 SP 的机制,类似于调用手动 SQL 命令,如“exec <sp_name>” 或类似 ADO.Net 的方式调用 SP。尽管如此,这两种方式都需要大量代码,并且需要手动编写。我太懒了。
- 所以我们陷入了死胡同,我们需要 Code First 方法的优秀特性,并且要克服 Code First 的局限性,我们需要 Database 方法的 SP 支持。
旁注:(可以跳过)
老天爷啊,ADO.Net 还是更棒的 J。EF 是 ADO.Net 之上的包装器,也就是说,就功能集而言,ADO.Net 是 EF 的超集。在 EF 中实现 ADO.Net 的所有可能性都需要时间来开发。6.0 版本已经足够好了,但仍有我上面描述的局限性。
没关系,我不会回到 ADO.Net 的世界,EF 相对于 ADO.Net 仍然有好处。(我在这里不解释)。
使用代码
如果您从 Database First 方法开始,自动生成的 DBContext 类将包含以下“OnModelCreating”重写函数。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
如果您尝试将自动生成的代码(来自 EF 的 Database First 方法)中的 POCOs 和 DBContext 类复制粘贴到您的 EF Code First 方法实现中,您将收到此异常。
EF 如何识别代码是作为 Code-First 还是 DB-First 运行?很简单,连接字符串。
- DB-First 的连接字符串包含加载 edmx 文件及相关架构和映射文件等所需的附加信息。
- Code-First 的连接字符串包含简单的连接字符串。
所以解决方案很简单,
- 使用 DB-First 方法创建您的模型,并保持连接字符串格式与 DB-First 方法相同。
- 根据需要扩展您的 POCOs 或 DB Context 文件。将 POCOs 和 DBContext 扩展到单独的文件中,作为部分类,这符合 SOLID 的开放-封闭原则。此步骤使您能够自由地使用 Code First 方法(而无需编写大量代码即可开始)。
- 既然您的目标是在 EF 方式下使用 SP,那么您(很可能)已经在 EF 模型中导入了所有的 SP(在上一步 # 1 中)。此 SP 导入执行多项操作:
- 在 DB-First EF 模型的相关配置文件中定义函数导入和架构。
- 在相同的配置文件中定义函数映射和参数信息等。
- 在您的自动生成的 DBContext 类中添加一个函数。这些函数接受相应 SP 的所有参数。
- 您可以开始使用您的混合方法了,但仍需考虑以下几点:
- 通常您不会有任何 Select SP,因为 LINQ 已被替代使用。使用 LINQ 或 Dynamic Linq 比编写大量 Select SP 要好得多。
- 通常您有大部分的 Update/Insert/Delete 的默认 SP 及少数特殊的 SP。
- 默认 SP(Insert/Update)需要几乎所有的列作为 SP 参数。这会导致自动生成的 SP 函数包含大量函数参数(等于相应表中的字段数)。这些参数大部分已在各自的 POCO 中提供。
- 那么为什么不将参数替换为单个基于 POCO 的参数呢?但请注意,您无法更改自动生成的代码。没关系,使用您的 DBContext 的另一个部分类来进行修改后的 SP 调用。
- 现在您可以开始使用了。
关注点
相关帖子即将发布
1) 如何在 EF 中使用 SP 维护并发(数据库设计方法和自动生成 Update & Insert SP)
2) 在 EF 中使用 SP 保存批量更新/插入 - SQL Server 2008+ 的表值函数
历史
尚未提供。