实体框架使用反射会损害性能吗?
我最终有两个领域,每个领域都有一些关于实体框架的问题,但让我提供一些背景知识,以便您知道我在什么上下文中要求此信息。
在我的工作地点,我的团队正在计划完全重写我们的应用程序结构,以便我们能够遵守更现代的标准。这次重写包括一个全新的数据层项目。在这个项目中,大多数团队都希望使用实体框架。我也想使用它,因为我在个人项目中使用它非常熟悉它。然而,一名团队成员强烈反对这一点,认为实体框架使用反射并会降低性能。他的另一个论点是 EF 使用生成的 SQL,其效率远低于存储过程。我不太熟悉 EF 的内部工作原理,并且我的搜索没有发现任何非常有用的东西。
这是我的问题。我试图让它们尽可能具体。如果您需要一些说明,请询问。
问题 1 问题 - 反射
- 关于 EF 使用反射并损害性能的说法是真的吗?
- 如果EF使用了反射,那么它在哪里使用呢?
- 有没有比较性能的资源?我可以用什么来客观地比较 .NET 中的数据访问技术,然后将其呈现给我的团队?
问题 2 问题 - SQL
- 这意味着什么?
- 是否可以使用存储过程来填充 EF 实体?
- 同样,是否有一些资源可以将生成的查询与存储过程进行比较,以及使用存储过程填充实体(如果可以)的含义是什么?
我自己做了一些搜索,但没有对 EF 的底层内容有太多了解。
I ultimately have two areas with a few questions each about Entity Framework, but let me give a little background so you know what context I am asking for this information in.
At my place of work my team is planning a complete re-write of our application structure so we can adhere to more modern standards. This re-write includes a completely new data layer project. In this project most of the team wants to use Entity Framework. I too would like to use it because I am very familiar with it from my using it in personal projects. However, one team member is opposed to this vehemently, stating that Entity Framework uses reflection and kills performance. His other argument is that EF uses generated SQL that is far less efficient than stored procedures. I'm not so familiar with the inner-workings of EF and my searches haven't turned up anything extremely useful.
Here are my questions. I've tried to make them as specific as possible. If you need some clarification please ask.
Issue 1 Questions - Reflection
- Is this true about EF using reflection and hurting performance?
- Where does EF use reflection if it does?
- Are there any resources that compare performance? Something that I could use to objectively compare technologies for data access in .NET and then present it to my team?
Issue 2 Questions - SQL
- What are the implications of this?
- Is it possible to use stored procedures to populate EF entities?
- Again are there some resources that compare the generated queries with stored procedures, and what the implications of using stored procedures to populate entities (if you can) would be?
I did some searching on my own but didn't come up with too much about EF under the hood.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
是的,它确实像许多其他 ORM (NHibernate) 和有用的框架(DI 工具)一样。例如,如果没有反射,WPF 就无法工作。
虽然自 .NET 1.0 以来的过去 10 年里,使用 Reflection 的性能影响并没有太大变化(尽管有所改进),但随着硬件速度的加快和可读性的总体趋势,它现在已不再那么令人担忧。
请记住,主要的性能影响是在反映又名绑定时发生的,它将类型元数据读入 xxxInfo(例如
MethodInfo
),这发生在应用程序启动时。调用反射方法肯定会慢一些,但不被认为是一个大问题。
更新
我已经使用 Reflector 查看了 EF 的源代码,我可以确认它大量使用了 Reflection。
Yes, it does like many other ORMs (NHibernate) and useful frameworks (DI tools). For example WPF cannot work without Reflection.
While the performance implications of using Reflection has not changed much over the course of the last 10 years since .NET 1.0 (although there has been improvements), with the faster hardware and general trend towards readability, it is becoming less of a concern now.
Remember that main performance hit is at the time of reflecting aka binding which is reading the type metadata into xxxInfo (such as
MethodInfo
) and this happens at the application startup.Calling reflected method is definitely slower but is not considered much of an issue.
UPDATE
I have used Reflector to look at the source code of EF and I can confirm it heavily uses Reflection.
问题 1 的答案:
您可以通过检查生成的 Foo.Designer.cs 文件来准确了解 EF 输出的内容。您将看到生成的容器不使用反射,但大量使用泛型。
以下是实体框架确实使用反射的地方:
Expression
接口用于创建 SQL 语句。 System.Linq 中的扩展方法基于表达式树的思想,它使用 System.Reflection 中的类型来表示函数调用和类型等。db.ExecuteStoreQuery("GetWorkOrderList @p0, @p1", ...)
,实体框架必须填充实体,并且至少必须检查跟踪提供的TEntity
类型。对问题 2 的回答:
确实,查询通常看起来很奇怪,但这并不表明它的效率较低。您将很难想出一个实际查询计划更糟糕的查询。
最重要的是,您当然可以使用存储过程,甚至可以使用带有实体框架的内联 SQL 来进行查询以及创建、更新和删除。
旁白:
即使它到处都使用反射,并且不允许您使用存储过程,为什么这会成为不使用它的理由呢?我认为您需要让您的同事证明这一点。
Answer for Issue 1:
You can take a look at exactly what is output by EF by examining the
Foo.Designer.cs
file that is generated. You will see that the resulting container does not use reflection, but does make heavy use of generics.Here are the places that Entity Framework certainly does use reflection:
Expression<T>
interface is used in creating the SQL statements. The extension methods inSystem.Linq
are based around the idea of Expression Trees which use the types inSystem.Reflection
to represent function calls and types, etc.db.ExecuteStoreQuery<TEntity>("GetWorkOrderList @p0, @p1", ...)
, Entity Framework has to populate the entity, and at very least has to check that theTEntity
type provided is tracked.Answer for Issue 2:
It is true that the queries are often strange-looking but that does not indicate that it is less efficient. You would be hard pressed to come up with a query whose acutal query plan is worse.
On top of that, you certainly can use Stored Procedures, or even Inline SQL with entity framework, for querying and for Creating, Updating and Deleting.
Aside:
Even if it used reflection everywhere, and didn't let you use stored procedures, why would that be a reason not to use it? I think that you need to have your coworker prove it.
我可以评论关于生成 EF 查询效率低于存储过程的问题 2。
基本上是的,有时生成的查询很混乱,需要一些调整。有许多工具可以帮助您纠正此问题,例如 SQL Profiler、LinqPad 等等。但最终生成的查询可能看起来像垃圾,但它们通常运行得很快。
是的,您可以将 EF 实体映射到过程。这是可能的,并且允许您控制一些令人讨厌的生成的 EF 查询。反过来,您还可以将视图映射到实体,从而允许您控制视图选择数据的方式。
我想不出资源,但我必须这么说。使用 EF 与 SQL 存储过程的比较就像苹果与橘子一样。 EF 提供了一种将数据库直接映射到代码的可靠方法。与 LINQ to Entity 查询相结合,您的开发人员可以快速生成代码。 EF 是一种 ORM,而 SQL 存储过程则不是。
I can comment on Issue 2 about Generated EF Queries are less efficient than Stored Procedures.
Basically yes sometimes the generated queries are a mess and need some tuning. There are many tools to help you correct this, SQL Profiler, LinqPad, and others. But in the end the Generated Queries may look like crap but they do typically run quickly.
Yes you can map EF entities to Procedures. This is possible and will allow you to control some of the nasty generated EF queries. In turn you could also map views to your entities allowing you to control how the views select the data.
I cannot think of resources but I must say this. The comparison to using EF vs SQL stored procedures is apples to oranges. EF provides a robust way of mapping your Database to your code directly. This combined with LINQ to Entity queries will allow your developers to quickly produce code. EF is an ORM where as SQL store procedures is not.
实体框架可能使用反射,但我不认为这会损害性能。基于反射的高端库通常使用轻量级代码生成来降低成本。他们仅检查每种类型一次以生成代码,然后从该点开始使用生成的代码。当您的应用程序启动时,您需要支付一点费用,但从那时起,成本可以忽略不计。
至于存储过程,它们比普通的旧查询更快,但这种好处常常被夸大了。主要优点是数据库将预编译并存储每个存储过程的执行计划。但数据库也会缓存它为普通旧式 SQL 查询创建的执行计划。因此,根据应用程序执行的查询数量和类型,这种好处会有很大差异。是的,如果需要,您可以将存储过程与实体框架一起使用。
The entity framework likely uses reflection, but I would not expect this to hurt performance. High-end librairies that are based on reflection typically use light-weight code generation to mitigate the cost. They inspect each type just once to generate the code and then use the generated code from that point on. You pay a little when your application starts up, but the cost is negligible from there on out.
As for stored procedures, they are faster than plain old queries, but this benefit is often oversold. The primary advantage is that the database will precompile and store the execution plan for each stored procedure. But the database will also cache the execution plans it creates for plain old SQL queries. So this benefit varies a great deal depending on the number and type of queries your application executes. And yes, you can use stored procedures with the entity framework if you need to.
我不知道 EF 是否使用反射(我不相信它会使用反射...我想不出必须在运行时确定哪些信息);但即使是这样,那又怎样呢?
.NET 中到处都使用反射(例如序列化器),其中一些反射始终被调用。
反射实际上并没有那么慢;尤其是在本次讨论的背景下。我想象进行数据库调用、运行查询、返回查询以及对对象进行水合的开销使反射的性能开销相形见绌。
编辑
Rick Strahl 关于反射性能的文章:.Net 反射和性能(旧的,但仍然相关)。
I don't know if EF uses reflection (I don't believe it does... I can't think of what information would have to be determined at run-time); but even if it did, so what?
Reflection is used all over the place in .NET (e.g. serializers), some of which are called all of the time.
Reflection really isn't all that slow; especially in the context of this discussion. I imagine the overhead of making a database call, running the query, returning it and hydrating the objects dwarf the performance overhead of reflection.
EDIT
Article by Rick Strahl on reflection performance: .Net Reflection and Performance(old, but still relevant).
实体框架生成的 SQL 查询很好,即使它们与 DBA 手工编写的不完全一样。
但是当涉及到基本类型的查询时,它会产生完全的垃圾。如果您计划使用 Table-per-Type 继承方案,并且您预计会对基本类型进行查询,那么我建议您谨慎操作。
有关这个奇怪缺点的更详细解释,请参阅我的问题 此处。特别注意该问题的公认答案——这可以说是一个错误。
至于反思的问题,我认为你的同事是在抓住救命稻草。反射不太可能成为应用程序中任何性能问题的根本原因。
Entity Framework generated sql queries are fine, even if they are not exactly as your DBA would write by hand.
However it generates complete rubbish when it comes to queries over base types. If you are planning on using a Table-per-Type inheritance scheme, and you anticipate queries on the base types, then I would recommend proceeding with caution.
For a more detailed explanation of this bizarre shortcoming see my question here. take special note of the accepted answer to that question --- this is arguably a bug.
As for the issue of reflection -- I think your co-worker is grasping at straws. It's highly unlikely that reflection will be the root cause of any performance problems in your app.
EF 使用反射。我没有检查它,我认为这是从数据库记录具体化实体实例时映射的要点。您会说列的名称是什么,属性的名称是什么,当执行数据读取器时,您必须以某种方式填充您只能通过其名称知道的属性。
我相信所有这些“类似性能”的问题都可以通过缓存映射所需的信息来正确解决。与与服务器的网络通信、执行复杂查询等相比,反射造成的性能影响可能不算什么。
如果我们谈论 EF 性能,请检查这两个文档: 第 1 部分 和 < a href="http://blogs.msdn.com/b/adonet/archive/2008/02/11/exploring-the-performance-of-the-ado-net-entity-framework-part-2.aspx" rel="nofollow">第 2 部分。它描述了人们有时认为 EF 非常慢的一些原因。
存储过程比 EF 查询更快吗?我的回答是:我不这么认为。 linq 的主要优点是您可以在应用程序中构建查询。当您需要诸如列表过滤、分页和排序+更改显示列数、加载相关实体等之类的内容时,这非常方便。如果您想在存储过程中实现此功能,您将有数十个用于不同查询配置的过程,或者您将使用动态sql。动态sql正是使用EF。但对于 EF,该查询具有编译时验证,而普通 SQL 则不然。性能上的唯一区别是当您将整个查询发送到服务器时以及当您仅发送 exec procecdeure 和参数时传输的数据量。
确实,查询有时非常奇怪。特别是继承有时会产生错误的查询。但这已经解决了。您始终可以使用自定义存储过程或 SQL 查询来返回实体、复杂类型或自定义类型。 EF 将为您具体化结果,因此您无需费心数据读取器等。
如果您想在呈现实体框架时保持客观,您还应该提及它的缺点。实体框架不支持命令批处理。如果您需要更新或插入多个实体,每个 sql 命令都有自己的数据库循环。因此,您不应该使用 EF 进行数据迁移等。EF 的另一个问题是几乎没有可扩展性的钩子。
EF uses reflection. I didn't check it by I think it is the main point of the mapping when materializing instance of entity from database record. You will say what is a column's name and what is the name of a property and when a data reader is executed you must somehow fill the property which you only know by its name.
I believe that all these "performance like" issues are solved correctly by caching needed information for mapping. Performance impact caused by reflection will probably be nothing comparing to network communication with the server, executing the complex query, etc.
If we talk about EF performance check these two documents: Part 1 and Part2. It describes some reason why people sometimes think the EF is very slow.
Are stored procedures faster then EF queries? My answer: I don't think so. The main advantage of the linq is that you can build your query in the application. This is extreamly handy when you need anything like list filtering, paging and sorting + changing number of displayed columns, loading realted entities etc. If you want to implement this in a stored procedure you will either have tens of procedures for diffent query configurations or you will use a dynamic sql. Dynamic sql is exactly what uses EF. But in case of EF that query has compile time validation which is not the case of plain SQL. The only difference in performance is the amount of transfered data when you send whole query to the server and when you send only exec procecdeure and parameters.
It is true that queries are sometimes very strange. Especially inheritance produces sometimes bad queries. But this is already solved. You can always use custom stored procedure or SQL query to return entities, complex types or custom types. EF will materialize results for you so you don't need to bother with data readers etc.
If you want to be objective when presenting Entity framework you should also mention its cons. Entity framework doesn't support command batching. If you need to update or insert multiple entities each sql command have its own roundrip to database. Because of that you should not use EF for data migrations etc. Another problem with EF is almost no hooks for extensibility.