2

I am using NHibernate and I want to control fetching related entities manually.

Here is my sample entity

public class Post
{
    public virtual long Id { get; set; }
    public virtual string Title { get; set; }
    public virtual User User { get; set; }
    public virtual IList<Like> Likes { get; set; }
    public virtual IList<Tag> Tags { get; set; }
}

The behvaiour I expect is as follows:

session.Query<Post>().ToList();

After this kind of query I want Post entities to have:

  1. Primitive properties are set
  2. User property is not null but only have Id property set.
  3. Likes and Tags are null or empty collection

-

session.Query<Post>()
    .Fetch(p => p.User)
    .Fetch(p => p.Tags)
    .ToList();

And after this kind of query I want Post entities to have:

  1. Primitive properties are set
  2. User property is not null and properties are set.
  3. Tags is not null and all items have all properties set
  4. Likes is null or empty collection

Basically what I want from NHibernate is, not to fetch any related entities unless I ask for it to fetch and not cause an NHibernate specific exception (LazyInitialization etc.) when I try to access not fetched properties. The behaviour I expect is not lazy nor eager.

Before "what have you tried" comments, I tried almost all combinations with LazyLoad(), Not, Fetch etc. in Fluent NHibernate mapping configuration along with both statless and stateful sessions.

Mehmet Ataş
  • 11,081
  • 6
  • 51
  • 78
  • Are you working with session closed context, or why you get lazy initialization exception? – Najera Apr 23 '15 at 16:05
  • I got lazy initialization exception when I use stateless session (session opened). I understand that it is how NHibernate works. I am just trying to find a configuration that will make NHibernate work according to my expectations. – Mehmet Ataş Apr 23 '15 at 16:12
  • Why you get an exception to an initialized properties? – Najera Apr 23 '15 at 17:18
  • Sorry I forgot to mention that I get lazy initialization exception when I do not call `Fetch(p => p.Likes)`. – Mehmet Ataş Apr 23 '15 at 17:24

2 Answers2

1

I can't figure out how to deal with uninitialized instances without validate before call a reference:

NHibernateUtil.IsInitialized(entityOrCollection)

And / or

NHibernateUtil.IsPropertyInitialized(obj, "propertyName")
Najera
  • 2,869
  • 3
  • 28
  • 52
  • I would avoid manual fetching. I would prefer to create Projections, and batch-fetching. But this answer is the best among the other solutions... – Radim Köhler Apr 24 '15 at 05:22
  • If he needs his domain entities this can be the answer, but im agree with you, using projections with DTOs is easier and can gain performance. – Najera Apr 24 '15 at 15:40
0

One option is to setting the other collections to null as soon as you loaded your collection,

var list = session.Query<Post>()
    .Fetch(p => p.User)
    .Fetch(p => p.Tags)
    .ToList();
list.ForEach(i => i.Likes = null);

But you should not persist them (since you are using a stateless session I don't believe you intend to persist them anyway).

Low Flying Pelican
  • 5,974
  • 1
  • 32
  • 43