Ayende @ Rahien

It's a girl

What is the story behind the Entity Framework vs. NHibernate posts?

A while ago I posted several posts about EF vs. NH. They generated quite a bit of commentary, but while I enjoyed the discussion, I had an ulterior motive for doing so.

I wanted to do this as a way to do a comparative research about the actual features that people would like to see in NHibernate.

Comments

Brian
01/29/2010 10:08 AM by
Brian

I feel used and, and... and dirty.

;-)

I'm just sorry I couldn't give meaningful contribution to the debate. I've enjoyed following it. It's been fun.

PS
01/29/2010 11:44 AM by
PS

the feature I wanted the most has been implemented recently already, namely lazy loaded properties. Good job on that one :)

Dmitry
01/29/2010 11:45 AM by
Dmitry

I believe it was determined that was biggest feature (besides LINQ) was that EF often uses unions instead of joins during eager loading to prevent loading lots of redundant data in multi-level entity graphs. Is a similar fetch mode going to be available in NHibernate? This would be especially useful when you need to do paging.

PS
01/29/2010 11:50 AM by
PS

actually there are still two more feature I would appreciate a lot, and that is being able to access output parameters and multiple result sets from stored procedures without having to resort to classic ADO.NET...

Demis Bellot
01/29/2010 12:32 PM by
Demis Bellot

Pretty clever :)

Hope it works - competition will make both software better.

Steve Py
01/29/2010 12:42 PM by
Steve Py

My vote would be to be able to re-associate dirty objects with a session. That and maybe finding some serious digging into whether a session can be a bit more robust around exception scenarios. (Less need to drop objects and reload in a new session.) Though if option 1 worked, at least then objects from the dead session could be re-attached.

I know I brought this up with you before. Still, for NHibernate or any ORM to work reliably in more stateful environments such as Windows apps, or even new stuff like Silverlight, the ability to reliably re-associate potentially dirty objects with a session (without forcing an update to the DB then and there) would be very useful.

Ayende Rahien
01/29/2010 01:08 PM by
Ayende Rahien

Steve,

NHibernate has good support for that, session.Merge()

Ayende Rahien
01/29/2010 01:10 PM by
Ayende Rahien

PS,

While NH support native SQL, there are some things that we are just going to consider outside our scope.

Stuff like the things you are talking about are such things. They are rare enough that we literally would invest more time in solving them than it would be worth.

Belvasis
01/29/2010 01:25 PM by
Belvasis

Yes, the ability to re-associate dirty objects with a session would be really helpful.

Then, i miss some way to intercept the collection loading process. There are often situations where i don't need the hole object graph of an 1:n association of an entity. Yes i could use Session or Mapping based filters, but thats not always possible when those filters depends on a specific context or situation.

But maybe i just miss something in the current NH implementation.

Karsten
01/29/2010 01:27 PM by
Karsten

I wanted to do this as a way to do a comparative research about

the actual features that people would like to see in NHibernate.

So what things do you see people want in NHibernate?

Ayende Rahien
01/29/2010 01:31 PM by
Ayende Rahien

Belvasis,

session.CreateFilter() ?

Ayende Rahien
01/29/2010 01:32 PM by
Ayende Rahien

Karsten,

Read the post comments.

tobi
01/29/2010 01:56 PM by
tobi

Now this feature request will be a bit uninformed because i never tries linq to nhibrenate in depth but it seemed to me that it was much inferior to linq2sql when i comes to query translation. I remember that group joins were not possible a few month ago (i think this is fixed?) and i don't know if i can use (First|Single)(OrDefault)? inside my query for example in a where statement. This is often useful to get the most recent subobject like the latest post in a forum thread. Also set operations are not fully supported. You might consider this out of your scope too (which is a legitimate choice) but I personally do not.

Belvasis
01/29/2010 02:01 PM by
Belvasis

@Ayende

yes I know this, but i don't want to access a session from within my entity. Let's assume an Employee entity has a collection for it's Appointments and a collection for it's WorkingTime. Now i want to calculate the remaining time for new Appointments in a specific date range as part of my business logic. So i don't need data from outside the given date range. And then what happens if i want to do Appointments.Add(new Appointment()) and the collection is not loaded? So i have to put this logic outside the entity what means, i have to refresh the entity afterwards to make the Appointment collection synchronized. But as i mentioned before, maybe i miss something or should think in different directions.

Ayende Rahien
01/29/2010 02:05 PM by
Ayende Rahien

You create two collections, you filter on one, based on the context, and you set the second AllAppointments as a bad with inverse="true", which won't load everything if you add it

Harry M
01/29/2010 03:06 PM by
Harry M

Component inheritance mapping +1

Jenser
01/29/2010 03:42 PM by
Jenser

Linq + 1

Dan Malcolm
01/29/2010 03:55 PM by
Dan Malcolm

Eager fetching was the biggest thing that came up for me.

The EF api (Include extension method) permits you to safely eager fetch multiple collection associations, with each eager fetch costing only an additional select and thus a predictable performance impact. This seems to be an ideal compromise for most scenarios and certainly the most sensible default. There could be performance issues if the where condition is expensive (e.g. ColumnName LIKE '%123%') as the table scan would be repeated for each association - might be a different strategy for that but I digress...

With NHibernate, the Criteria API (SetFetchMode) seems to offer similar flexibility at face value, but you can't realistically eager fetch multiple collection associations.

That doesn't mean rewriting NH query engine to do unions though - the existing "subselect" fetch mode could be used to provide a quick win. We would need to support the following scenario:

  1. Fetching strategy for the Blog.Posts collection is set to subselect

  2. Collection is marked for eager fetching criteria.SetFetchMode("Posts", FetchMode.Eager)

  3. Subselect should be issued immediately after the select query for the root entity

This would offer equally flexible control over collection fetching and possibly better performance in case of expensive where conditions. It would also resolve the paging issue.

At the moment, if you do this, NH uses an outer join to fetch the collection. I'd have expected that setting FetchMode.Eager would use the fetch defined on the collection in the mapping.

Kelly Bourg
01/29/2010 04:16 PM by
Kelly Bourg

Even though I posted about MultiQuery support for sql-queries. I have to agree with the other posters about eager fetching multiple associations. IMO this should be top priority. This is always a pain point for me and my team (we have a legacy DB that requires many joins :( ).

Dan Ambrose
01/29/2010 06:58 PM by
Dan Ambrose

I would like to ability to assign the result of a query to a property.

So for every entity/class, it would execute a defined query that uses other data in that class and assign the result to the property. Basically:

Class1.Property1 = (select * from table1 where....)

Ayende Rahien
01/29/2010 07:26 PM by
Ayende Rahien

Dan,

That feature exists, it is called a Forumla

Chuck
01/30/2010 02:02 AM by
Chuck

Aha...the slow hand penetrates the shield...

vigj
01/30/2010 05:42 PM by
vigj

what i would like more is something like that:

to have the possibility to map some objects on one db (e.g. a sql server database), some others on another db (e.g. a mysql database) but have the possibility to use them as if they were persisted in one db only (joins, relationships, hql...)

beleive or not i have several use cases where this would be incredibly useful to me

Ayende Rahien
01/30/2010 05:51 PM by
Ayende Rahien

Vigj,

Oh, it is easy, create a db link between them and move on.

The performance would SUCK, but it is possible.

Ayende Rahien
01/30/2010 05:58 PM by
Ayende Rahien

Or look at NHibernate Shards

cowgaR
01/31/2010 03:12 PM by
cowgaR

ah NHibernate Shards...looks like an abandoned project to me...

even the source (e.g. java material) is looking abandoned (by google), beta 3 being the "release" version if I remember correctly

what is the story behind it? some momentum was started there by you couple of months ago, but I've looked on it 2 weeks ago but didn't see any activity on this field...

I understand it's free project, but I would even pay for such a kind of feature... Ayende, start "donating shards" page ;)

Ayende Rahien
01/31/2010 04:13 PM by
Ayende Rahien

cowgaR,

I can't comment on the Hibernate one, but the NHibernate one is functional.

Steve
01/31/2010 09:29 PM by
Steve

I suspose you're going to build in a VS designer for NHi bernate and then sell NH to MS? :)

The only features I kept hearing about were:

  1. EF is from MS and not open source

  2. EF has a designer and NH doesn't

  3. Throw in the Linq part but I think that is covered

Sorry for my sarcasm in advance. :)

Quintin
02/01/2010 02:51 AM by
Quintin

Oren,

I thought Nhibernate is a direct port of Hibernate and all features are directed by Hibernate.

I am all in for Linq 2 NH(since its on top of criteria)..

Stuart Jones
02/01/2010 08:12 AM by
Stuart Jones

Personally I think Linq and querying in general is absolutely an issue for newbies and more experienced developers alike. We use NH throughout our project, and writing queries is a pain. Both Query API and HQL are not compile time safe, and as a result our finder/fetch methods are the hardest things to write in our system accurately.

We've started to us the Lamda Extensions in NH - this seems to provide a good work around and is already increasing productivity - however they do feel like a hack to me in the way they work. Perhaps native support for this would be good.

Does anyone know when the new Linq provider will actually come out? Steve Strong keeps alluding to "only a few weeks"....

Ayende Rahien
02/01/2010 08:19 AM by
Ayende Rahien

Quintin,

NHibernate IS a port of Hibernate, but we are not limiting ourselves to what Hibernate supports.

NHibernate has a whole set of features & bug fixes that Hibernate does not support

Quintin
02/01/2010 09:09 AM by
Quintin

Oren,

Unrelated but, why is implementing L2NH (apart from the basic features in 1.0) taking so much time? Is it too complicated a task implementing a Linq provider (esp. since e EF supports it with a lot of advanced options)?

Ayende Rahien
02/01/2010 09:26 AM by
Ayende Rahien

Quintin,

Supporting a basic Linq provider is hard, but doable.

Supporting an advanced Linq provider is three orders of magnitude harder.

Karsten
02/01/2010 11:14 AM by
Karsten

Karsten,

Read the post comments.

No I was asking for what you concluded. Since this was your intend with the post, why not share it?

Ayende Rahien
02/02/2010 08:23 PM by
Ayende Rahien

Karsten,

See the commit log :-)

Graham
03/02/2010 06:08 PM by
Graham

My vote is similar to one above, make the session more stable so that if it fails for an non-critical DB issue (timeout, connection lost) that won't have impacted data anyway, you can just retry the Flush/Commit without having to dump the session and reload everything.

Really annoying (as it's best practice to retry AFAIK) and never understood why tbh

Comments have been closed on this topic.