Skip to content

NH-3872 - EntityLoader ignores subselect fetching option #1346

Open
@nhibernate-bot

Description

@nhibernate-bot

visubesy created an issue — 20th May 2016, 16:48:08:

Problem

EntityLoader doesn't override the property Loader.IsSubselectLoadingEnabled. That means that NHibernate won't generate subselects even if they were configured in the mapping. This can lead to performance problems (N+1 problem).

Remark: The property Loader.IsSubselectLoadingEnabled is processed in Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, bool returnProxies, IResultTransformer forcedResultTransformer).

Possible solution

Override Loader.IsSubselectLoadingEnabled in EntityLoader by calling Loader.HasSubselectLoadableCollections(). This is already done by CriteriaLoader, QueryLoader and CollectionLoader.

I don't know if this could produce any unwanted side-effects.

Example (Fluent NHibernate)

If the Abc instances are loaded by NHibernate using batch fetching, there won't be a single SELECT with subselect for the AbcArraySize instances. Instead there will be one SELECT for each ArraySize instance.


public class AbcMap : ClassMap<Abc>
{
	public AbcMap()
	{
		// ...

		BatchSize(640);

		HasMany(x => x.ArraySizes).KeyColumn(AbcArraySizeMap.ColumnAbcId)
			.CollectionType<MyListType<AbcArraySize>>()
			.ReadOnly()
			.Cascade.Evict()
			.Not.KeyNullable().Not.KeyUpdate()
			.Inverse()
			.Fetch.Subselect()
			.Not.LazyLoad();
	}
}

public class AbcArraySizeMap : ClassMap<AbcArraySize>
{
	internal const string ColumnAbcId = "ABC_ID";

	public AbcArraySizeMap()
	{
		// ...
	}
}

Workaround (well, not really)

One can add a call to BatchSize in the above HasMany mapping. There still won't be a subselect as intended but at least the generated SELECTs for AbcArraySize will use batch fetching.


visubesy added a comment — 20th May 2016, 16:54:48:

In the above description, it should read "Instead there will be several SELECTs to load the AbcArray instances, one for each Abc instance" instead of "Instead there will be one SELECT for each ArraySize instance". I can't edit the description.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions