.net ORM 比较
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5101974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
.net ORM Comparison
提问by Timo Willemsen
I was talking with someone about the Entity Framework, and I'm not really into it yet, but I'd like to learn it. However, I'm still kinda confused whether I should learn it or not. I've heard a lot of people saying you shouldn't use the entity framwork, however I haven't heared any arguments why that is.
我正在和某人谈论实体框架,我还没有真正深入研究它,但我想学习它。但是,我仍然有点困惑我是否应该学习它。我听到很多人说你不应该使用实体框架,但是我没有听到任何争论为什么会这样。
So my question is, what are the pro's and con's of using the Entity Framework compared to other products. Like
所以我的问题是,与其他产品相比,使用实体框架的优缺点是什么。喜欢
- NHibernate
- DataObjects.Net
- etc..
- NHibernate
- 数据对象网
- 等等..
In terms of ease of use, testability, semantics...
在易用性、可测试性、语义方面...
I know there are some duplicatequestionsabout this. But they are all kinda outdated (2008,2009) and to be honest, the arguments are also lacking something. I know Entity Framework 4.0 is available, and I haven't found a good (complete) comparison yet.
我知道有一些关于此的重复问题。但它们都有些过时(2008、2009),老实说,这些论点也缺乏一些东西。我知道 Entity Framework 4.0 可用,但我还没有找到一个好的(完整的)比较。
Answers
答案
Some of the nice people here have answered my question by explaining some details on the different frameworks. Thought it might be good to show them here for future reference.
这里的一些好人通过解释不同框架的一些细节回答了我的问题。认为在这里展示它们以供将来参考可能会很好。
回答by Diego Mijelshon
Since J. Tihon did a great job on explaining EF features, I'll just list the areas where NHibernate runs circles around EF:
由于 J. Tihon 在解释 EF 特性方面做得很好,我将仅列出 NHibernate 围绕 EF 运行的领域:
- Caching
- EF has nothing out of the box; there's just an unsupported sample
- NH has complete caching support, including DB-based invalidation. It's also extensible and provider-based, meaning it works with different types of local and distributed caches
- Batching
- EF has none
- NH has extensive support for lazy-loading groups of entities or collections at once (in any DB), and persisting changes in the same way (Oracle and SQL Server). There's also MultiQueries and Future Queries, allowing you to arbitrarily group different queries to be sent in one roundtrip.
- User types
- EF has no extensibility at all. It doesn't even support Enum properties
- No type mappings are hardcoded in NH. You can extend it to support any value types you can create, modify the way existing types are mapped, etc
- Collection support
- EF supports only simple collections of entities. Many-to-many always uses a composite key
- NH supports collections of entities, value types, component types, and also indexed collections and dictionaries (where both the key and the value can be of any type). Many-to-many collections with their own key are supported (idbag)
- Logging
- EF has no logging out of the box. There's the same unsupported sample listed above
- NH has extensive logging, allowing you to debug issues easily. It uses log4net by default, but you can use any logging framework you want
- Querying
- EF has LINQ as the main query language. LINQ has a high impedance when mapping to relational databases. EF's provider does not support using entities as parameters; you always have to use Ids. There's also a query language that's poorly documented
- NH has LINQ (not as complete as EF's, though), HQL, QueryOver and Criteria.
- Event system and interceptors
- EF has almost nothing
- NH has a powerful event system that allows you to extend or replace its behavior at any point of the session lifecyle: loading objects, persisting changes, flushing, etc.
- 缓存
- EF 没有任何开箱即用的东西;只有一个不受支持的样本
- NH 具有完整的缓存支持,包括基于数据库的失效。它也是可扩展和基于提供者的,这意味着它适用于不同类型的本地和分布式缓存
- 批处理
- EF 没有
- NH 广泛支持一次(在任何数据库中)延迟加载实体或集合组,并以相同的方式(Oracle 和 SQL Server)持久化更改。还有 MultiQueries 和 Future Queries,允许您任意分组不同的查询以在一次往返中发送。
- 用户类型
- EF 根本没有可扩展性。它甚至不支持 Enum 属性
- NH 中没有硬编码类型映射。您可以扩展它以支持您可以创建的任何值类型,修改现有类型的映射方式等
- 收藏支持
- EF 仅支持简单的实体集合。多对多总是使用复合键
- NH 支持实体集合、值类型、组件类型以及索引集合和字典(其中键和值都可以是任何类型)。支持具有自己密钥的多对多集合 (idbag)
- 日志记录
- EF 没有开箱即用的注销功能。上面列出了相同的不受支持的示例
- NH 具有广泛的日志记录,可让您轻松调试问题。它默认使用 log4net,但你可以使用任何你想要的日志框架
- 查询
- EF 以 LINQ 作为主要查询语言。LINQ 在映射到关系数据库时具有高阻抗。EF 的提供者不支持使用实体作为参数;你总是必须使用 Id。还有一种查询语言的记录很差
- NH 有 LINQ(虽然不如 EF 完整)、HQL、QueryOver 和 Criteria。
- 事件系统和拦截器
- EF几乎一无所有
- NH 有一个强大的事件系统,允许您在会话生命周期的任何点扩展或替换其行为:加载对象、持久更改、刷新等。
I think extensibility is the main selling point. Every aspect of NH is correctly decoupled from the rest, using interfaces and base clases that you can extend whenever you need to, and exposed in configuration options.
我认为可扩展性是主要卖点。NH 的每个方面都与其他方面正确解耦,使用您可以随时扩展并在配置选项中公开的接口和基类。
EF follows the usual MS pattern of making things closed by default, and we'll see what's extensible later.
EF 遵循默认情况下使事物关闭的通常 MS 模式,我们稍后会看到什么是可扩展的。
回答by J. Tihon
I spend a huge amount of time to bend the Entity Framework to my needs and can therefore say, that it fulfills most of the requirements you want from an ORM. But some aspects are far too complex, as other ORMs have shown that it can be made easier.
我花费了大量时间来使实体框架满足我的需求,因此可以说它满足了您希望从 ORM 中获得的大部分要求。但是有些方面太复杂了,因为其他 ORM 已经表明它可以变得更容易。
For example, getting started with the Entity Framework is fairly easy, since you can just fire up the Designer in Visual Studio and have a working ORM in a matter of minutes. But you end up with Entity-Classes tied to the ObjectContext created by the designer (this can be avoided using a custom T4 Template). This is not necessarly a bad thing, but it's that kind of Microsoft "Getting Started" approaches, that you don't want to use in a real application.
例如,实体框架的入门相当容易,因为您只需在 Visual Studio 中启动设计器并在几分钟内拥有一个可以工作的 ORM。但是您最终会得到与设计器创建的 ObjectContext 相关联的实体类(使用自定义 T4 模板可以避免这种情况)。这不一定是件坏事,但它是那种 Microsoft“入门”方法,您不想在实际应用程序中使用。
But if you dive deeper into the Entity Framework you can see, how you can avoid most of it's pitfalls: The Designer generates an EDMX file, which (if you look at it in an XML editor) is nothing more than a combination of the three main aspects of an ORM, the physical storage (your database), the conceptual model (your entity classes) and the mapping between both of them. The custom build-action applied to .edmx files in Visual Studio will split those 3 parts into three separate files and adds them to the assembly as embedded resources. When creating an ObjectContext the path to those three files is used in the ConnectionString (which always looks a bit confusing to me). What you can actually do here, is do all this by yourself. This means writing the storage schema, conceptual model and mapping in an XML editor (much like NHibernate) and embed these to the assembly containing your model.
但是,如果您深入研究实体框架,您会发现如何避免其中的大部分陷阱:设计器生成一个 EDMX 文件,该文件(如果您在 XML 编辑器中查看)只不过是三者的组合ORM 的主要方面、物理存储(您的数据库)、概念模型(您的实体类)以及它们之间的映射。在 Visual Studio 中应用于 .edmx 文件的自定义构建操作会将这 3 个部分拆分为三个单独的文件,并将它们作为嵌入资源添加到程序集中。创建 ObjectContext 时,ConnectionString 中使用了这三个文件的路径(这对我来说总是有点混乱)。你实际上可以在这里做的,就是你自己做这一切。这意味着编写存储模式,
The base Entity Framework base class "ObjectContext" can than be constructed from those three files (it takes an MetadataWorkspace and EntityConnection) but the point is, that you have full control over how the ObjectContext get's created. This opens the door for a lot of functionality you might not expect from the Entity Framework. For Example: you can embed multiple SSDL storage schemas in the same assembly to match a specific database-type (i usually add one for SQL Server and one for SQL Server CE 4.0). And create a constructor overload that chooses the appropriate storage schema for a specific kind of DbConnection.
基础实体框架基类“ObjectContext”可以从这三个文件(它需要一个 MetadataWorkspace 和 EntityConnection)构建,但关键是,您可以完全控制 ObjectContext 的创建方式。这为您可能无法从实体框架中获得的许多功能打开了大门。例如:您可以在同一个程序集中嵌入多个 SSDL 存储架构以匹配特定的数据库类型(我通常为 SQL Server 添加一个,为 SQL Server CE 4.0 添加一个)。并创建一个构造函数重载,为特定类型的 DbConnection 选择适当的存储模式。
Since you have your own ObjectContext implementation now, you can implement various interfaces on it. Like your own IRepository, but since i like the ObjectContext approach, i create something like:
由于您现在拥有自己的 ObjectContext 实现,因此您可以在其上实现各种接口。就像你自己的 IRepository,但因为我喜欢 ObjectContext 方法,我创建了类似的东西:
interface ICatalog
{
IEntitySet<Article> { get; }
void Save();
}
interface IEntitySet<T> : IQueryable<T>
{
void Add(T);
void Remove(T);
}
class EntityFrameworkCatalog : ICatalog
{
...
}
But creating a Repository if you have an Entity Framework ObjectContext is really easy, plus you get an IQueryable. Based on this information you can avoid having strong class coupling between your services and the ORM and completly mock out the Entity Framework in tests. Also, when testing your Entity Framework implementation, you can use a SQL Server CE database during unit-tests to ensure that your mappings are fine (usually the different between the storage schema for CE and the full blown SQL Server is just a few data-types). So you can actually test all behaviors of your Entity Framework implemantion just fine.
但是,如果您有实体框架 ObjectContext,那么创建存储库真的很容易,而且您还可以得到一个 IQueryable。基于此信息,您可以避免在您的服务和 ORM 之间存在强类耦合,并在测试中完全模拟实体框架。此外,在测试您的实体框架实现时,您可以在单元测试期间使用 SQL Server CE 数据库来确保您的映射良好(通常 CE 的存储架构和成熟的 SQL Server 之间的差异只是一些数据-类型)。因此,您实际上可以很好地测试实体框架实现的所有行为。
This makes Entity Framework place nicely with modern software concepts, but it doesn't enforce such practices on you, which makes the "Getting Started" easier.
这使得 Entity Framework 与现代软件概念很好地结合在一起,但它不会对您强制执行此类实践,这使得“入门”更容易。
Now to the complex bits: The Entity Framework has a small set of supported CLR types, which basically only include the primitive ones, like ints, strings and byte-arrays. It also provides some level of complex-types, which follow the same rules. But what if you have a complex entity property such as a DOM representation of a document, which you would like to have serialized to XML in the database. As far as i know, NHibernate provides a feature called IUserType, which allows you to define such a mapping for you. In Entity Framework this gets much more complicated, but it's still in pretty in it's own way. The conceptual model allows you to include assembly-internal complex-types (as long as you tell the ObjectContext about it (ObjectContext.CreateProxyTypes(Type[])). So you can create a wrapper for your original type, that is only known to the Entity Framework like so:
现在是复杂的部分:实体框架有一小组受支持的 CLR 类型,它们基本上只包括原始类型,如整数、字符串和字节数组。它还提供了某种级别的复杂类型,它们遵循相同的规则。但是,如果您有一个复杂的实体属性(例如文档的 DOM 表示),您希望将其序列化为数据库中的 XML,该怎么办?据我所知,NHibernate 提供了一个叫做 IUserType 的特性,它允许你为你定义这样的映射。在实体框架中,这变得更加复杂,但它仍然以它自己的方式漂亮。概念模型允许你包含程序集内部的复杂类型(只要你告诉 ObjectContext 关于它(ObjectContext.CreateProxyTypes(Type[]))。所以你可以为你的原始类型创建一个包装器,
class Document : IXmlSerializable { }
class Article
{
public virtual Document Content { get; set; }
}
internal class EntityFrameworkDocument : Document
{
public string Xml
{
get
{
// Use XmlSerializer to generate the XML-string for this instance.
}
set
{
// Use XmlSerializer to read the XML-string for this instance.
}
}
}
Altough the EF can now return those serialized documents from the storage, writing them to it, requires you to intercept the storing of an Article and replace a simple Document with the EntityFrameworkDocument one, to ensure that EF can serialize it. I'm sure other ORMs does that pretty easily and it get's worse. Currently there is no way, to do the same with System.Uri class (which is immutable, but would otherwise work) or an Enum. Apart from those restrictions you can fit the EF to most of your needs. But you will spend a lot time on it (like I did).
尽管 EF 现在可以从存储中返回那些序列化的文档,并将它们写入其中,但需要您拦截文章的存储并将简单的 Document 替换为 EntityFrameworkDocument ,以确保 EF 可以对其进行序列化。我确信其他 ORM 很容易做到这一点,而且情况会变得更糟。目前没有办法对 System.Uri 类(它是不可变的,但可以正常工作)或 Enum 做同样的事情。除了这些限制之外,您还可以让 EF 满足您的大部分需求。但是你会花很多时间在上面(就像我一样)。
Since my experience with other ORMs is limited, I would summarize:
由于我对其他 ORM 的经验有限,我总结一下:
- Entity Framework is in the GAC, even in the Client Profile
- Entity Framework can be customized to represent even complex entity types (Including some self-referencing many-to-many for example, or the the XML serialization above)
- It can be "abstracted" away, so you can stick to IRepository etc.
- IQueryable implementation (altough it's not that complete as DataObjects.Net)
It only requires System.Data and System.Data.Entity, you can even include multiple storage schemas for other providers which would normally require a reference, but if you stick to DbConnection you can just do this:
ICatalog Create(DbConnection connection, string storageSchemaPath) ICatalog CreateMySql(DbConnection mySqlConnection) { return Create(connection, "res://Assembly/Path.To.Embedded.MySql.Storage.ssdl"); }
- 实体框架在 GAC 中,甚至在客户端配置文件中
- 可以自定义实体框架以表示甚至复杂的实体类型(例如,包括一些自引用的多对多,或上面的 XML 序列化)
- 它可以被“抽象”掉,所以你可以坚持使用 IRepository 等。
- IQueryable 实现(虽然它不像 DataObjects.Net 那样完整)
它只需要 System.Data 和 System.Data.Entity,您甚至可以为通常需要引用的其他提供程序包含多个存储模式,但如果您坚持使用 DbConnection,您可以这样做:
ICatalog Create(DbConnection connection, string storageSchemaPath) ICatalog CreateMySql(DbConnection mySqlConnection) { return Create(connection, "res://Assembly/Path.To.Embedded.MySql.Storage.ssdl"); }
EditI recently found out, that if your entities and your "catalog" implementation are in the same assembly, you can use internal properties for an XML serialization process. So instead of deriving an internal EntityFrameworkDocumentfrom Documentyou could add an internal Property called Xmlto the Documentclass itself. This still only applies if you have full control over your entities, but it removes the need to intercept any changes to the catalog, to make sure that your derived class is used. The CSDL looks the same, EF just allows the mapped property to be internal. I still have to ensure that this would work in Medium-Trust environments.
编辑我最近发现,如果您的实体和您的“目录”实现在同一个程序集中,您可以使用内部属性进行 XML 序列化过程。因此EntityFrameworkDocument,Document您可以添加一个Xml对Document类本身调用的内部属性,而不是从内部派生。这仍然仅适用于您完全控制实体的情况,但它不需要拦截对目录的任何更改,以确保使用您的派生类。CSDL 看起来一样,EF 只允许映射的属性是内部的。我仍然必须确保这在 Medium-Trust 环境中有效。
回答by Dean
Hope fully these will help
希望完全这些会有所帮助
回答by Eduardo
When we use ADO.NET from scratch sooner or later we get frustrated and start looking for other solutions. I have tested many of them. Most of those ORM frameworks have lots of features and requires lots of knowledge. Some seem very easy at the beginning (eg: EF, Castle ActiveRecord) but there are many things you shall care about:
当我们从头开始使用 ADO.NET 时,我们迟早会感到沮丧并开始寻找其他解决方案。我已经测试了其中的许多。大多数 ORM 框架都有很多功能,需要很多知识。有些一开始看起来很容易(例如:EF,Castle ActiveRecord),但有很多事情你应该关心:
- Caching
- Many-to-many relationships
- Lazy loading
- Inheritance
- Composite keys
- How to encapsulate infratructure from callers
- How SQL statements are generated
- Performance
- How to make advanced database queries
- 缓存
- 多对多关系
- 延迟加载
- 遗产
- 复合键
- 如何封装来自调用者的基础设施
- SQL语句是如何生成的
- 表现
- 如何进行高级数据库查询
If you are an experienced developer and you are ready for all those pitfalls and stuffs then I ask you: Are your workmates also?
如果您是一位经验丰富的开发人员,并且准备好应对所有这些陷阱和东西,那么我问您:您的同事也是吗?
There are easier ways to code ADO.NET and not loose control of what is happening. Take a look at PainlessDAL.
有更简单的方法来编写 ADO.NET 代码,并且不会对正在发生的事情失去控制。看看PainlessDAL。
"Elegant" coding is not always the best way.
“优雅”的编码并不总是最好的方式。

