.net中的EF比你想象的更智能

💡 原文中文,约10000字,阅读约需24分钟。
📝

内容提要

本文讨论了如何优化实体框架(EF)代码,包括创建表的方法、更新实体的子项集合、访问更改的作用域、避免数据不一致的问题以及提高代码可读性和灵活性的建议。了解EF的内部工作原理可以简化开发过程并提高性能。

🔎

延伸解读

DbContext 中不定义 DbSet 也能建表

文章指出,只要在 OnModelCreating 中通过 modelBuilder.Entity<User>() 等方式配置实体,EF 就会创建对应表,无需显式声明 DbSet。这样做的好处是限制对某些表的直接访问,在 DDD 中很常见,也便于实现泛型操作。访问时改用 dbContext.Set<User>() 即可。

更新子集合:清空再填充,让 Change Tracker 干活

面对父实体及其子项的增删改,手动计算差异往往代码冗长且易错。文章建议直接 user.Addresses.Clear() 再重新 Add,EF 的 Change Tracker 会自动生成 DELETE、UPDATE、INSERT 语句。但要注意,带 Id 的子项会被更新,不带 Id 的会被插入,并非全部删除重建。

跨服务共享同一实体:便利与风险并存

由于 Change Tracker 会按主键返回已跟踪的实体,即使在不同服务中重新查询,拿到的也是同一个对象。因此一个服务对实体的修改,另一个服务能立即看到。这既保证了数据最新,也可能导致意外提交他人未察觉的更改,使用时需留意作用域边界。

Find 与 First 的性能差异及事务保护

Find() 按主键查询,首次访问数据库后会将实体缓存,后续调用直接返回缓存,避免重复 SELECT;而 First() 是扩展方法,即使实体已跟踪仍会发起查询。此外,用 BeginTransaction 包裹多次 SaveChanges,可在业务逻辑出错时回滚,防止数据不一致。

❓

Q&A

如何优化实体框架(EF)代码以提高可读性?

可以将复杂的 Linq 查询拆分为多个条件子句,以提高代码的可读性和灵活性。

在EF中,如何避免数据不一致的问题?

使用TransactionScope可以确保在业务逻辑出错时避免数据不一致。

EF的Change Tracker有什么作用?

EF的Change Tracker能够自动处理实体的添加、更新和删除,简化了代码。

在EF中,如何简化更新父实体及其子实体的过程?

可以通过清空子项集合并重新填充来简化更新过程。

使用Find()方法有什么优势?

使用Find()方法可以避免重复查询同一实体,提高性能。

为什么开发人员不愿意阅读EF的文档?

尽管EF很受欢迎,但开发人员往往懒得阅读文档,导致冗余代码的产生。

🏷️

标签

➡️

继续阅读