59

我在这里看到了一个未回答的问题。

我的问题是——

EF 是否真的为大型应用程序做好了生产准备?

这个问题源于这些潜在的问题——

  1. EF 将所有记录拉入内存然后执行查询操作。当表有大约 1000 条记录时,EF 会如何表现?
  2. 对于简单的编辑,我必须拉记录编辑它,然后使用推送到数据库SaveChanges()
4

5 回答 5

152

我遇到过类似的情况,我们有一个大型数据库,其中有许多表,每个表有 7 到 1000 万条记录。我们使用实体框架来显示数据。为了获得出色的表现,这就是我学到的;我对实体框架的 10 条黄金法则

  1. 了解仅在需要实际记录时才调用数据库。所有操作都只是用于进行查询(SQL),因此请尝试仅获取一条数据而不是请求大量记录。尽可能修剪 fetch 大小

  2. 是的,(在某些情况下存储过程是更好的选择,它们并不像某些人认为的那样邪恶),您应该在必要时使用存储过程。将它们导入您的模型并为它们导入函数。也可以直接调用它们 ExecuteStoreCommand()、ExecuteStoreQuery<>()。函数和视图也是如此,但 EF 有一种非常奇怪的调用函数“SELECT dbo.blah(@id)”的方式。

  3. EF 在必须填充具有较深层次结构的实体时执行较慢。对层次结构较深的实体要格外小心

  4. 有时,当您请求记录并且不需要修改它们时,您应该告诉 EF 不要查看属性更改 (AutoDetectChanges)。这样记录检索要快得多

  5. 数据库的索引很好,但在 EF 的情况下它变得非常重要。您用于检索和排序的列应该被正确索引。

  6. 当您的模型很大时,VS2010/VS2012 模型设计师会变得非常疯狂。所以把你的模型分成中型模型。存在一个限制,即来自不同模型的实体不能共享,即使它们可能指向数据库中的同一个表。

  7. 当您必须在不同位置对同一实体进行更改时,请使用同一实体,进行更改并仅保存一次。关键是要避免检索相同的记录,进行更改并多次保存。(真正的性能增益提示)。

  8. 当您只需要一两列中的信息时,尽量不要获取完整的实体。你可以直接执行你的 sql 或者有一个迷你实体。您可能还需要在应用程序中缓存一些常用数据。

  9. 交易很慢。小心他们。

  10. SQL Profiler 或任何查询分析器都是您的朋友。在开发应用程序时运行它以查看 EF 发送到数据库的内容。当您在您的应用程序中使用 LINQ 或 Lambda 表达式执行连接时,EF 通常会生成一个 Select-Where-In-Select 样式的查询,该查询可能并不总是表现良好。如果您发现任何此类情况,请卷起您的袖子,在 DB 上执行连接并让 EF 检索结果。(这个我忘了,最重要的!)

如果你牢记这些事情,EF 应该提供与普通 ADO.NET 几乎相似的性能,如果不一样的话。

于 2013-10-11T07:43:31.617 回答
21

1. EF 将所有记录拉入内存,然后执行查询操作。当表有大约 1000 条记录时,EF 会如何表现?

这不是真的!EF 只获取必要的记录,查询被转换为适当的 SQL 语句。EF 可以在本地缓存对象DataContext(并跟踪对实体所做的所有更改),但只要您遵循规则仅在需要时保持上下文打开,就不会成为问题。

2. 对于简单的编辑,我必须拉记录编辑它,然后使用 SaveChanges() 推送到数据库

这是真的,但除非你真的看到性能问题,否则我不会这样做。因为 1. 不正确,所以在保存之前您只会从数据库中获取一条记录。您可以通过将 SQL 查询创建为字符串并将其作为纯字符串发送来绕过它。

于 2013-10-11T06:22:07.247 回答
7
  1. EF 将您的 LINQ 查询转换为 SQL 查询,因此它不会将所有记录拉入内存。生成的 SQL 可能并不总是最有效的,但一千条记录根本不是问题。
  2. 是的,这是一种方法(假设您只想编辑一条记录)。如果您要更改多条记录,则可以使用一个查询将它们全部获取,SaveChanges()并将保留所有这些更改。
于 2013-10-11T06:25:12.693 回答
6

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 等......

于 2017-01-30T21:37:15.620 回答
4

你的问题没有简单的答案。主要是关于你想用你的数据做什么?您一次需要这么多数据吗?

EF 将您的查询转换为 SQL,因此此时内存中没有对象。当您获取数据时,所选记录就在内存中。如果您要选择大量大型对象,那么如果您需要对它们进行全部操作,那么它可能会成为性能杀手。

如果您不需要全部操作它们,您可以禁用更改跟踪并稍后为您需要操作的单个对象启用它。

所以你看到它取决于你的应用程序类型。如果您需要高效地处理大量数据,请不要使用 OR-Mapper!

否则 EF 很好,但请考虑一次您真正需要多少对象以及您想用它们做什么。

于 2013-10-11T06:37:29.253 回答