Override lazy loading behavior 'lazy=false' - nhibernate

I would like to override the default lazy loading behavior which is set in mappings as 'lazy=false'. Can't change it as many parts of existing application depend on this setting.
After spent some hours on it I didn't find a solution so I'm asking here.
How to do this?
What I want to achieve is to fine tune my query to load only what is needed.
This is what I've tried already:
Using QueryOver api:
var properties = session.QueryOver<Property>()
.Fetch(prop => prop.Transactions).Eager
.Fetch(prop => prop.Districts).Eager
//I dont want to load those entities below so I mark
//them as lazy - IT DOESN'T WORK
//I can see in SQL that they are getting loaded in separate queries
.Fetch(prop => prop.Districts.First().Aliases).Lazy
.Fetch(prop => prop.Districts.First().PolygonPoints).Lazy
.Skip(i * pageSize)
.Take(pageSize)
.List();
Using Criteria api:
var criteria = session.CreateCriteria<Property>();
criteria.SetFetchMode("Transactions", NHibernate.FetchMode.Join);
criteria.SetFetchMode("Districts", NHibernate.FetchMode.Join);
criteria.SetFetchMode("Districts.Aliases", NHibernate.FetchMode.Select); // tried Lazy too
criteria.SetFetchMode("Districts.PolygonPoints", NHibernate.FetchMode.Select); // tried Lazy too
criteria.AddOrder(NHibernate.Criterion.Order.Asc("Id"));
criteria.SetFirstResult(i * pageSize);
criteria.SetMaxResults(pageSize);
var properties = criteria.List<Property>();
Using any of the above methods 'Aliases' and 'PolygonPoints' are always being loaded when calling List<>(). I don't need them in my process.
I'm using Nhibernate 4.0.
Any ideas?

We cannot override mapping in this case. We can do it opposite way - have lazy in place - and use eager fetching for querying.
The decision process (of reference loading) is done outside of the query, ex post. So it could be pre-loaded, but cannot be avoided.
Solution here could be of two types.
The first is preferred (by me) - do your best and make laziness the default: Ayende -
NHibernate is lazy, just live with it
Use projections. Instruct NHibernate to create just one query, use transformer to get expected object graph - without any proxies in it
There is pretty clear example how to (properly) use projection list even for references:
Fluent NHibernate - ProjectionList - ICriteria is returning null values
And we would also need Custom result transformer, which will ex-post create all the references from the returned data:
Custom DeepResultTransfomer

Related

Is any method exist for QueryOver like Load for Get?

I'm using Fluent NHibernate and try to do many updates. First came in mind is code like this:
using (ISession s = OpenSession())
using (s.BeginTransaction())
{
IList<SomeType> items s.QueryOver<SomeType>()
.Where(someCondition)
.List();
items.ForEach(i => {
i.Foo = "bar";
s.Update(i);
});
s.Transaction.Commit();
}
But problem is in that every updating item must be loaded before do update. So database queried twice. In SQL it can be done with one query and i believe exist some way to do this with one query in NHibernate. And found doc for Load method that not actually load item from db and only work with some proxy instead and hit database only when i do update/delete.
Exist some method in NHibernate that load not items itself but proxy like Load?
For now for update large data best way is use HQL or raw SQL how mentioned #DavidOsborne.
I unfortunately not found any other methods that works lazy as Load method.

EF: How to do effective lazy-loading (not 1+N selects)?

Starting with a List of entities and needing all dependent entities through an association, is there a way to use the corresponding navigation-propertiy to load all child-entities with one db-round-trip? Ie. generate a single WHERE fkId IN (...) statement via navigation property?
More details
I've found these ways to load the children:
Keep the set of parent-entities as IQueriable<T>
Not good since the db will have to find the main set every time and join to get the requested data.
Put the parent-objects into an array or list, then get related data through navigation properties.
var children = parentArray.Select(p => p.Children).Distinct()
This is slow since it will generate a select for every main-entity.
Creates duplicate objects since each set of children is created independetly.
Put the foreign keys from the main entities into an array then filter the entire dependent-ObjectSet
var foreignKeyIds = parentArray.Select(p => p.Id).ToArray();
var children = Children.Where(d => foreignKeyIds.Contains(d.Id))
Linq then generates the desired "WHERE foreignKeyId IN (...)"-clause.
This is fast but only possible for 1:*-relations since linking-tables are mapped away.
Removes the readablity advantage of EF by using Ids after all
The navigation-properties of type EntityCollection<T> are not populated
Eager loading though the .Include()-methods, included for completeness (asking for lazy-loading)
Alledgedly joins everything included together and returns one giant flat result.
Have to decide up front which data to use
It there some way to get the simplicity of 2 with the performance of 3?
You could attach the parent object to your context and get the children when needed.
foreach (T parent in parents) {
_context.Attach(parent);
}
var children = parents.Select(p => p.Children);
Edit: for attaching multiple, just iterate.
I think finding a good answer is not possible or at least not worth the trouble. Instead a micro ORM like Dapper give the big benefit of removing the need to map between sql-columns and object-properties and does it without the need to create a model first. Also one simply writes the desired sql instead of understanding what linq to write to have it generated. IQueryable<T> will be missed though.

Fluent NHibernate LazyLoad Issues

I couldn't find an answer to this issue so I assume it is something I am doing wrong.
I have a PersistenceModel set up where I have set a convention as follows: -
persistenceModel.Conventions.Add(DefaultLazy.Always());
However, for one of the HasManyToMany relationships in one of my entities I want eager loading to take place which I am setting up as follows: -
HasManyToMany(x => x.Affiliates).Not.LazyLoad();
Intuitively, I expect eager loading to take place as I am overriding the lazy load default that I have specified as a convention but it still lazy loads. If I set the DefaultLazy convention to never and then set LazyLoad on an individual relationship it doesn't work either.
Any ideas?
When you set Not.LazyLoad(), you tell NHibernate to load Affiliates when the parent loads. NHibernate will do this by performing another select on the Affliates many-to-many table regardless of whether you access the Affiliates collection or not. NHibernate is using another select because that is the default fetching mode. You want to override fetching mode as well, either in the query or in the mapping. To do it in the mapping, add the following:
HasManyToMany(x => x.Affiliates)
.Not.LazyLoad()
.Fetch.Join();
You might also want to include a ".Cascade.AllDeleteOrphan()" if you want NHibernate to persist new Affiliaites added to the collection and delete orphaned ones. If you do not do this, you will have to explicitly call session.Save(newAffiliate). Otherwise you'll receive a TransientObjectException when your Affiliates collection contains a new Affiliate.
It may be one stupid thing to ask, but have you execute the query inside your session? Say,
Using(var session = OpenSession())
{
session.Query<Entity>().ToList();
}
I had this problem before, and finally realized the objects that I was accessing hadn't been queried before disposing the session.

How do I use Fluent Nhibernate many-to-many for optimal performance?

I have a product table that has a many-to-many relation to itself (using a two-column many-to-many table) and I have set it up in Fluent NHibernate with the following code:
public class ProductConfiguration : ClassMap<Product>
{
public ProductConfiguration()
{
Table("Product");
Id(p => p.Id).GeneratedBy.Guid();
Map(p => p.Name).Not.Nullable().Length(254);
Map(p => p.Description).Not.Nullable().Length(1000);
Map(p => p.CreatedAt).Not.Nullable();
HasManyToMany(p => p.CrossSell)
.Table("ProductCrossSell")
.ParentKeyColumn("Id")
.ChildKeyColumn("ProductId");
}
}
My MVC application has two pages that uses this setup:
Index - Uses a generic repository GetAll method to display all products.
Detail - Uses a generic repository GetById method to display one product and any related cross sell products setup in the many-to-many realation.
It looks like NHibernate is set to LazyLoad the many-to-many by default so when I fire up the application and watch it in profiler I can see that it does LazyLoad the many-to-many with the following alert "Use of implicit transactions is discouraged".
How do I get rid of this alert? I couldn't find any information on how to wrap a LazyLoad inside a transaction to get rid the alert. Is it even possible?
Is there a way to not lazyload this by telling NHibernate that whenever I ask for GetById make sure to join the tables a get everything in one query? I tried using .Fetch.Join() in the many-to-many mapping but that also affected my GetAll query which now displays a joined result set as well which is incorrect.
What is the best apprach for this kind of simple scenario?
Thanks
The way to get rid of the warning is to access the object graph and fully populate the UI elements inside a single transaction.
Not by configuration. You can create an HQL query that eager fetches the association and use that query for a specific view. I would stick with lazy loading and not make that optimization unless needed. The HQL would be:
return session.CreateQuery("from ProductionConfiguration pc join fetch pc.CrossSell where pc.Id = ?")
.SetGuid(0, id)
.List<ProductConfiguration>();
All collections are lazily loaded in NHibernate by default.
You must be triggering loading with a call of some kind (maybe even with the debugger watches)

NHibernate DTO Parent child relation

I have som entities and now want to make some DTO´s based on there entities using nhibernate.
I have a Service - Allocation -Ressource where allocation describes how the ressource is allocated for the service.
I want a DTO like
ServiceDTO
-Name
-RessourceDTO
where RessourceDTO also has a name.
In the examples I have see for NHibernate projection/DTO you either use properties or constructor. If I use The Constructor approach I would have something like
ServiceDTO(Name, List
But I can't figure out how to make this work.
Another approach is to extract all the services and then loop through them and hit the database each time, or extract a larger result and then make the DTO's
What is the best approach? I going to hide all of this inside a repository.
How about
public ServiceDTO GetDTOFor(int Id);
{
var service = Session.CreateCriteria<Service>()
.Add(Restrictions.Eq("Id", id)
.SetFetchMode("Resources", fetchmode.eager) // eager load resources
.uniqueResult<Service>();
return new ServiceDTO(service.Name, service.Resources.ToList()) // Copy the Resources
}