views:

525

answers:

4

So like many developers before me, I am at the crossroads of choosing an ORM to learn thoroughly and move forward with for future projects. I have been playing with Entity Framework and so far like what I see, although I have only tried simple things, CRUD with clearly defined table relationships with a 1-1 table-entity mapping. I did some googling on Entity Framework and found mostly negative feedback... what concerns me the most is the complexity of the mapping xml and generated object classes... As well as the fact that they are dependent on component classes of the EF and therefore need to be respected as such when it comes to object model design considerations. As of now I am leaning towards NHibernate... for the relative simplicity of the mapping files and the fact that it can work with POCO objects that I craft to meet my object model design needs. There is even a LINQ provider for it, as well as third party code generation tools. However... I don't wish to throw EF out the window just yet. Does anyone know of a successful production app written with EF? Or on the technical side, any reasons I would want to lean towards EF now e.g. has corporate backing, is new and therefore more likely to grow in feature set over time while NH has reached the equilibrium of maturity? I don't mean to start a color war here, I'm just looking for positive things people may have to add about the EF before I make my decision.

Thanks!

+2  A: 

The problem is with this type of question is that there is an element of "religion" in peoples choice of frameworks, and ORM's inspire quite a lot of passion.

So at the risk of certain flames...I personally am not a huge fan of the Entity Framework, I can see where it would be pretty good to take a legacy system and ER model and map it, but I think in the longer term (and my use case) is more built around a Domain Model design and for my Entities to be mapped to that. There is a nice blog post here that I tend to agree with.

I think that I like the approach that products like NHibernate and Eco take. And currently I am experimenting with a true OODBMS (instead of an ORM) with DB4Objects and am very impressed so far.

Tim Jarvis
I bet EF v4 will please you more - support for true POCO, domain-driven design and more. The current version is indeed a ..... compromise :-) at best.
marc_s
I'll have to check it out.
Tim Jarvis
DB4O is amazing. The speed both in queries as in devtime are just mindblowing. I didn't experiment with a client/server architecture yet so I can't judge on that, but I am rather confident in that. If only my boss was as excited about it as I am :P
borisCallens
+10  A: 

Although I tend to agree with Tim about the "religious" element of framework choices, I still find it a bit odd that so many people are willing to comment on the EF when they so clearly haven't bothered to learn how it works. The EF, it turns out, would be a lousy version of NHibernate, just as hammers make poor screwdrivers. It is important to understand the EF on its own terms.

Before I address some of the points raised in comments here, I'll add that we have just shipped version 2 of a production web app with 0 lines of SQL and 100% of all DB access done through either the EF or the ASP.NET membership API to our clients. I speak here with real-world experience with using the EF, something which, regretfully, is clearly not true of the authors of most of the comments on the EF I've seen thus far.

In general, I think it's a mistake to extend your entity types. That the author of the blog post Tim cited (1) wasn't aware it was possible and (2) thinks this is the route to implement DDD tells me all I need to know about his real-world EF experience: He hasn't got any.

POCO support became a very big deal to users of certain ORMs because they didn't have a functional LINQ implementation for many years. Since you were essentially stuck with whatever type objects came out of the black box, having control over the parent type became a very big deal. So big, in fact, that writing your "POCOs" with every member declared public virtual began to be seen as no big deal. On which planet is this a "plain" type? It's a proxy base, not a POCO. The so-called "POCOs" aren't POCOs at all. It's just that they prefer to compromise on encapsulation and performance rather than on parent type. It's probably a legitimate compromise within the limitations of their toolset, but nothing to get cocky about.

But the EF works differently; it's every bit as easy to materialize an arbitrary type via LINQ projections as the type you actually mapped. If you're building something to send objects over the wire instead of to be used internally, and must have clients which can't depend on the EF, then you use RIA services or write an ADO.NET Data Service. All the hard work will be done for you. The EF is the basis for a family of tools handling the problem of projecting data in a DB onto various types of clients, not a single, standalone tool which attempts to handle every single data transformation an app might need internally, in one fat framework. Let the EF handle projection from RDBMSs into object space. You can then use, for example, LINQ to Entities to project into persistence-ignorant types, or RIA services to project onto a Silverlight-friendly wire format. Asking one tool to handle every projection any app might ever need is begging to be stuck in a ghetto with that tool.

The EF is based around the notion of "value objects." These are types with properties but no behaviors. It turns out that value objects work very well for certain specific problems, like sending data over a wire or sitting in the "no man's land" between the RDBMS and OO programming. It's important to understand the separation of concerns here: The point of the entity types is to get the RDB data into the object space. You can then write business types which implement your app, and project the entity types onto the business types. You then have the freedom to implement your business types with zero compromises for persistence. And you can change your RDB schema when need be. You need only change your entity mapping and BO projections, rather than the BOs themselves.

Craig Stuntz
Real world experience was what I was looking for;In the end it may make sense to separate entity classes from behavior classes, although after reading up on Rockford Lhotka's CSLA framework and even writing my own "ORM" inspired by it, I became pretty attached to the idea of self containment when it comes to logic encapsulation. It looks like the EF would be best in service oriented apps where the app logic lives on the service, but I still need data objects to send to the client... EF entities fit this perfectly, and can be sent/received by the logic objects service side.
Avi
+1  A: 

We've been using NHibernate at InterWorks for 4 years now. It has worked great for us and we have built another layer on top of it to simplify usage (similar to Castle ActiveRecord, which we were unaware of at the time).

The downsides of NHibernate is the learning curve, lack of a strong GUI tool(we use our own MyGeneration templates to generate objects), and OK community support. We have put a lot of effort into making it work for us and have spent quite a bit of time training new team members on NHibernate and the framework we have built around it.

Since we build mostly custom software, it is hard for us to justify the overhead of rebuilding our framework, but most likely in the next two years we will move to the Entity Framework for a couple of very basic reasons. (1) Better documentation and larger support community (it will happen quickly) and (2) Easier to find people with experience in EF, thus eliminating some training costs.

Those are not true today, but they will be pretty quickly with the next release of EF in VS.NET 2010. It has really matured and with the built in VS.NET support it is coming around nicely. We've done some basic tests with it, but I do not claim to have extensive experience with EF.

It to MS a while to get with the program, but now that they have the EF will be here for a long time to come and will become the standard. If you don't have experience in either ORM, I would start learning EF, it will be better for your career in the long run.

Cole Shelton
+2  A: 

Short answer: Wait until EF 4.0

Long answer:

I'm wrapping up a medium-sized EF 1.0 project now (also ASP.NET MVC). I also have experience with NHibernate. Aside from the common CRUD mappings, we did quite a bit of inheritance modeling. Overall my feelings about it are mixed.

A few observations:

The best thing I can say about EF 1.0 is that it has great LINQ integration. It is better than Linq to NHibernate (in its current release).

EF can handle the interesting inheritance mappings well, but you turn up A LOT of mapping errors trying to get it right. The documentation isn't super helpful here and there isn't yet a lot of community support. You just have to figure it out.

The designer is buggy and doesn't support everything the EF can do. You often find yourself editing the XML mapping files by hand. The designer creates errors in otherwise correct mapping xml. In fact, we've had so many issues with the designer that we'll go into the XML first, rather than let the designer update the mappings. I'd say this is a problem I have with Microsoft products in general: they build products with geared toward tooling rather than libraries. In this case, they rushed the tooling because the XML is equally bad.

The XML is, er, verbose. EF 1.0 requires a lot of mapping information. Contrast NHibernate's XML, which only deals with the mapping itself and doesn't require a conceptual definition or storage definition file, or, better yet, a tool like Fluent NHibernate, which lets you specify your mappings in code.

I, personally, prefer to write classes that can themselves be persisted (POCO) rather than deal with a separate data entity model. Craig's point about public virtual notwithstanding, I prefer NHibernate's proxy approach. I have to disagree with Craig on the intent of the EF. I don't think they intend that you create a mapping layer between the EF and your business objects. As partial classes, the intent seems to be that you add behavior to your entities in order to create a full OO class. With that in mind, you can't unit test EF 1.0 without jumping through a lot of hoops.

Perhaps the biggest irritation with EF is the lack of transparent lazy loading. That truly sucks.

I will wait until EF 4.0 comes out before I willingly use it again.

lordinateur
You're irritated with not having lazy loading because you're trying to user entity types directly instead of projecting. When you project, all the loading is handled automatically instead of having to eager load or explicitly call Load. Of course it hurts to swim upstream. The question is why you're so convinced that those of us floating downstream on inner tubes are doing things wrong while you struggle and curse.
Craig Stuntz
Craig, you'll have to point to some examples of the approach you're advocating. Creating a mapping layer between my POCO objects and EF isn't exactly floating downstream and it isn't in keeping with the direction from the ADO.NET team, who advocate partials to add behavior to entities -- and EF 4.0 is going POCO. As for lazy loading, even with your approach you run into loading issues when using inheritance where subclasses may have divergent navigation properties.
lordinateur
I have a talk on this coming up at the free, online CodeRage conference in about a month from now. Tune in if you're interested. Mapping entities to business types *is* easy with LINQ, it's just that users of other ORMs aren't used to working this way. Sorry, you're just flat wrong about subtypes; that's trivial in LINQ. I do understand that developers unable to use LINQ would find this difficult, but they'll just need to catch up.
Craig Stuntz
Ok, well I'm no expert but I feel pretty comfortable with LINQ. EF->POCO projections is usually easy enough, but POCO->EF I'll wait for your talk. I'm not sure what lazy loading has to do with LINQ. I'm talking about within the EF. Let's say you have a supertype Order and two subtypes: CustomerOrder and EmployeeOrder where CustomerOrder.Customer and EmployeeOrder.Employee are divergent navigation properties. If you then have an IEnumerable<Order> with both types, you will have to check ((CustomerOrder).CustomerReference.IsLoaded and handle appropriately. How does LINQ help you with that?
lordinateur
What LL has to do with LINQ: It's entirely automatic; **L2E coalesces nulls**. Presuming that, for the sake of argument (your app may be entirely different; this is a representative example), that the reason you want Customer and Employee in a single list is to get at the related Person from o in Context.Orders let c = o as CustomerOrder let e = o as EmployeeOrder select new { Order = o, Person = o.Person ?? e.Person }. In short: Don't think in terms of materializing entities; that's the way ORMs stuck with one type work. Think in terms of materializing the info your BOs actually *need*.
Craig Stuntz
"o.Person ?? e.Person" should read "c.Person ?? e.Person". Mea culpa.
Craig Stuntz
So, your argument is that my BO has the abstract Order AND the typed Order's (CustomerOrder/EmployeeOrder) divergent properties? In your example, the project is an anonymous type, but I would likely use typed BOs...like CustomerOrder or EmployeeOrder. Now I'm back to mapping a behavioral class to a value class - basically using an internal state object with change tracking. Without the ORM/LINQ, I'd have passed in the data to the behavior class's constructor: CustomerOrder(CusomterOrderInfo info). Now I'd have to manage a separate, parallel object graph of state. This isn't floating.
lordinateur
I think the way you're using 'entities' is confusing. Do you mean 'don't think in terms of materializing BOs'? Entities are just stateful objects with identity not determined by the values of properties. That's just what an ORM is in the business of materializing/persisting.
lordinateur
Projecting to a non-anon type is just as easy as projecting to an anon type. "Entity" in the **Entity** Framework has a precise and rather obvious meaning, as distinct from "entity" outside of the EF. Read "subtype of EntityObject" if you prefer, but that's hard to fit in a length-limited comment. Mapped types (whether "POCO" or not) are not the same as BOs (separation of concerns); treating them as the same is bad design. Yes, it's harder to track changes if you project to *true* POCOs (not proxy bases), but I'll pay that price for clean separation of concerns and no runaway state in the app.
Craig Stuntz
I hope you won't mind me linking to your own blog post related to this discussion: http://blogs.teamb.com/craigstuntz/2008/07/17/37825/Although over a year old now, it may add value for a reader of this thread. The problems with the designer corrupting the edmx are frustration in EF 1.0 (EF 3.5). I'll keep an eye out for your presentation.
lordinateur
Craig, having had a chance to watch your presentation, I thought I'd append a link and some thoughts. The talk (http://blogs.teamb.com/craigstuntz/2009/09/11/38394/) was very interesting and I really like the implications of projecting onto the business objects for testing and OO encapsulation. However, I think the objections concerning mapping from your POCOs back to the EDM still stand. Without change-tracking in your POCOs, you have to build custom mapping to your data access layer. Whether that's a worthwhile trade-off should be understood up-front by anyone following your approach.
lordinateur