我在这里看到了一个未回答的问题。
我的问题是——
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 很好,但请考虑一次您真正需要多少对象以及您想用它们做什么。