实体框架如何适用于大量记录?

Abh*_*eet 51 c# database-design entity-framework entity-framework-6

在这里看到一个未回答的问题.

我的问题是 -

EF真的可以为大型应用做好准备吗?

问题源于这些基本问题 -

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

Sim*_*low 132

我遇到了类似的情况,我们有一个大型数据库,每个表有700万到1000万个记录.我们使用Entity框架来显示数据.为了获得不错的表现,这就是我所学到的; 我对实体框架的10条黄金规则:

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

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

  3. 当必须使用深层次结构填充实体时,EF执行速度较慢.对具有深层次结构的实体要非常小心

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

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

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

  7. 当您必须在不同位置对同一实体进行更改时,请使用同一实体,进行更改并仅保存一次.重点是AVOID检索相同的记录,进行更改并多次保存.(实际业绩增益提示).

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

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

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

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

  • 我在银行应用程序上工作,SP是一个很大的帮助.我不能说"嘿!我们现在正在使用ORM,所以让我们丢弃所有已经工作多年的忠实存储过程,让我们从头开始写EF中的所有内容" - "为什么?" - "因为我爱EF!" 至于"DEV DEFINE MODELS,EF构建数据库和查询,以及DB FOLK只需要确保数据库运行快速" - 这可能是您的情况,但对于企业级应用程序,表,SP,功能由单独的开发人员维护,我们称之为使用TSQL和PLSQL专业知识的DB开发人员.希望你一定听说过他们! (13认同)
  • 对于第8个子弹:获取AutoMapper并使用`Project().到<>()`. (4认同)
  • 是啊.但是,一年之后,我可以得出结论,你不能再使用SP了.但问题是,数据库设计者受到这种威胁,因为这是他们可以控制的最后一件事.但他们不明白数据库设计已改为维护.开发人员定义模型,EF构建数据库和查询,而DB民众只需要确保数据库快速运行并正确设置索引.我根本不再使用SP,TSQL或SSMS,而且我的项目具有高度可扩展性和极快的性能.2号不正确. (4认同)
  • @ppumkin:有时候,有些情况下你无法有效地从EF发出声明.在那种情况下,存储过程会有所帮助.但它确实是你的选择.如果您可以在不使用SP的情况下实现目标,请不要费心使用它们. (3认同)

Mar*_*zek 19

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

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

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

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

  • 这个答案有误导性.是的,如果它有一组作为查询或内存列表提供的值,EF会执行加入内存,基本上对于任何不是来自数据库的内容,EF将从数据库中提取所有内容,执行操作在内存中并返回结果.如果要进行实验,请使用列表或数组执行表连接,并查看其行为方式.截至目前,使用EF 6.0,这仍然是正确的. (3认同)

Bot*_*000 6

  1. EF将您的LINQ查询转换为SQL查询,因此它不会将所有记录都拉入内存.生成的SQL可能并不总是最有效的,但是一千条记录根本不会成为问题.
  2. 是的,这是一种方式(假设您只想编辑一条记录).如果要更改多个记录,则可以使用一个查询获取所有记录,SaveChanges()并将保留所有这些更改.


tcw*_*cks 5

EF不是一个糟糕的ORM框架.它是一个有自己特色的不同的.比较Microsoft Entity Framework 6,而不是NetTiers,它由Microsoft Enterprise Library 6提供支持.

这是两个完全不同的野兽.接受的答案非常好,因为它经历了EF6的细微差别.需要了解的关键是每个ORM都有自己的优点和缺点.将项目要求及其数据访问模式与ORM的行为模式进行比较.

例如:NetTiers将始终为您提供比EF6更高的原始性能.然而,这主要是因为它不是点击ORM并且作为生成ORM的一部分,您将优化数据模型,在相关时添加自定义存储过程等...如果您使用相同的方法设计数据模型EF6的努力你可能会接近相同的性能.

还可以考虑修改ORM吗?例如,使用NetTiers,您可以向代码匠模板添加扩展,以包含您自己的设计模式,超出基本ORM库生成的模式.

还要考虑EF6大量使用反射,而NetTiers或任何由Microsoft Enterprise Library驱动的库将大量使用泛型.这是两种完全不同的方法.为什么这样?因为EF6基于动态反射,而NetTiers基于静态反射.哪个更快,哪个更好完全取决于ORM所需的使用模式.

有时混合方法效果更好:例如考虑用于Web API OData端点的EF6,用NetTiers和Microsoft Enterprise Library包含自定义存储过程的几个大型表,以及一些用自定义构建的写入对象缓存包装的大型masterdata表.初始加载使用ADO数据读取器将记录集流式传输到内存高速缓存中.

这些都是不同的,它们都有最适合的场景:EF6,NetTiers,NHibernate,Wilson OR Mapper,Dev Express的XPO等......