我在这里看到了一个未回答的问题。
我的问题是——
EF 是否真的为大型应用程序做好了生产准备?
这个问题源于这些潜在的问题——
- EF 将所有记录拉入内存然后执行查询操作。当表有大约 1000 条记录时,EF 会如何表现?
- 对于简单的编辑,我必须拉记录编辑它,然后使用推送到数据库
SaveChanges()
我在这里看到了一个未回答的问题。
我的问题是——
EF 是否真的为大型应用程序做好了生产准备?
这个问题源于这些潜在的问题——
SaveChanges()
我遇到过类似的情况,我们有一个大型数据库,其中有许多表,每个表有 7 到 1000 万条记录。我们使用实体框架来显示数据。为了获得出色的表现,这就是我学到的;我对实体框架的 10 条黄金法则:
了解仅在需要实际记录时才调用数据库。所有操作都只是用于进行查询(SQL),因此请尝试仅获取一条数据而不是请求大量记录。尽可能修剪 fetch 大小
是的,(在某些情况下存储过程是更好的选择,它们并不像某些人认为的那样邪恶),您应该在必要时使用存储过程。将它们导入您的模型并为它们导入函数。也可以直接调用它们 ExecuteStoreCommand()、ExecuteStoreQuery<>()。函数和视图也是如此,但 EF 有一种非常奇怪的调用函数“SELECT dbo.blah(@id)”的方式。
EF 在必须填充具有较深层次结构的实体时执行较慢。对层次结构较深的实体要格外小心
有时,当您请求记录并且不需要修改它们时,您应该告诉 EF 不要查看属性更改 (AutoDetectChanges)。这样记录检索要快得多
数据库的索引很好,但在 EF 的情况下它变得非常重要。您用于检索和排序的列应该被正确索引。
当您的模型很大时,VS2010/VS2012 模型设计师会变得非常疯狂。所以把你的模型分成中型模型。存在一个限制,即来自不同模型的实体不能共享,即使它们可能指向数据库中的同一个表。
当您必须在不同位置对同一实体进行更改时,请使用同一实体,进行更改并仅保存一次。关键是要避免检索相同的记录,进行更改并多次保存。(真正的性能增益提示)。
当您只需要一两列中的信息时,尽量不要获取完整的实体。你可以直接执行你的 sql 或者有一个迷你实体。您可能还需要在应用程序中缓存一些常用数据。
交易很慢。小心他们。
SQL Profiler 或任何查询分析器都是您的朋友。在开发应用程序时运行它以查看 EF 发送到数据库的内容。当您在您的应用程序中使用 LINQ 或 Lambda 表达式执行连接时,EF 通常会生成一个 Select-Where-In-Select 样式的查询,该查询可能并不总是表现良好。如果您发现任何此类情况,请卷起您的袖子,在 DB 上执行连接并让 EF 检索结果。(这个我忘了,最重要的!)
如果你牢记这些事情,EF 应该提供与普通 ADO.NET 几乎相似的性能,如果不一样的话。
1. EF 将所有记录拉入内存,然后执行查询操作。当表有大约 1000 条记录时,EF 会如何表现?
这不是真的!EF 只获取必要的记录,查询被转换为适当的 SQL 语句。EF 可以在本地缓存对象DataContext
(并跟踪对实体所做的所有更改),但只要您遵循规则仅在需要时保持上下文打开,就不会成为问题。
2. 对于简单的编辑,我必须拉记录编辑它,然后使用 SaveChanges() 推送到数据库
这是真的,但除非你真的看到性能问题,否则我不会这样做。因为 1. 不正确,所以在保存之前您只会从数据库中获取一条记录。您可以通过将 SQL 查询创建为字符串并将其作为纯字符串发送来绕过它。
SaveChanges()
并将保留所有这些更改。EF 不是一个糟糕的 ORM 框架。这是一个不同的,有自己的特点。将 Microsoft Entity Framework 6 与由 Microsoft Enterprise Library 6 提供支持的 NetTiers 进行比较。
这是两种完全不同的野兽。公认的答案非常好,因为它体现了 EF6 的细微差别。要理解的关键是每个 ORM 都有自己的长处和短处。将项目需求及其数据访问模式与 ORM 的行为模式进行比较。
例如:NetTiers 将始终为您提供比 EF6 更高的原始性能。然而,这主要是因为它不是一个点击 ORM 并且作为生成 ORM 的一部分,您将优化您的数据模型,在相关的地方添加自定义存储过程,等等......如果您使用相同的设计数据模型EF6 的努力可能会接近相同的性能。
还考虑你可以修改ORM吗?例如,使用 NetTiers,您可以向 codesmith 模板添加扩展,以在基础 ORM 库生成的内容之上包含您自己的设计模式。
还要考虑 EF6 大量使用反射,而 NetTiers 或任何由 Microsoft Enterprise Library 提供支持的库将大量使用泛型。这是两种完全不同的方法。为什么这样?因为 EF6 基于动态反射,而 NetTiers 基于静态反射。哪个更快,哪个更好完全取决于 ORM 所需的使用模式。
有时混合方法效果更好:考虑例如用于 Web API OData 端点的 EF6、一些使用 NetTiers 和 Microsoft 企业库以及自定义存储过程包装的大型表,以及一些使用自定义构建的通过对象缓存写入的大型主数据表。初始加载记录集使用 ADO 数据读取器流式传输到内存缓存中。
这些都是不同的,它们都有最适合的场景:EF6、NetTiers、NHibernate、Wilson OR Mapper、来自 Dev Express 的 XPO 等......
你的问题没有简单的答案。主要是关于你想用你的数据做什么?您一次需要这么多数据吗?
EF 将您的查询转换为 SQL,因此此时内存中没有对象。当您获取数据时,所选记录就在内存中。如果您要选择大量大型对象,那么如果您需要对它们进行全部操作,那么它可能会成为性能杀手。
如果您不需要全部操作它们,您可以禁用更改跟踪并稍后为您需要操作的单个对象启用它。
所以你看到它取决于你的应用程序类型。如果您需要高效地处理大量数据,请不要使用 OR-Mapper!
否则 EF 很好,但请考虑一次您真正需要多少对象以及您想用它们做什么。