Nhibernate generating OUTER JOIN for a fetch

Despite setting up mapping to be Not.Nullable() and Not.LazyLoad()

For some reason NH is joining a table twice, once with a INNER JOIN to appease the WHERE, and secondly on a OUTER JOIN to select the data.

Surely, as we've already JOINED the data, it would make sense to just use the joined table...

SELECT
     ...Tables..
from Tasks taskentity0_,
 outer Cases caseentity1_,
 outer Grades gradeentit2_,
 Cases caseentity5_ 
WHERE
....

My LINQ query for this is:

IQueryable<TaskEntity> tasks = TaskRepo.Find(
    t => t.DueDate <= DateTime.Now
      && (t.TaskInitials == userInitials || (t.TaskInitials == "" || t.TaskInitials == null))
      && t.Team.GST.Any
                    (x => x.Initials == userInitials
                        && x.WorkType.WorkTypeCode == t.WorkType.WorkTypeCode
                        && x.Team.TeamCode == t.Team.TeamCode
                    )
      && (t.Case.CaseOnHold <= DateTime.Now || t.Case.CaseOnHold == null || (t.SingleTask == "M" || t.SingleTask == "m"))
      && (t.Case.CaseMatter.StartsWith("0") || t.Case.CaseMatter.StartsWith("9"))
                ).Fetch(t => t.Case,FetchProvider)

My Reference Mapping:

        References(x => x.Case).Column("ta_c_ref").Not.Nullable();

Thoughts?

We are using the repository pattern, and have reimplemented the Fetch extension method to work this way (Hence passing the FetchProvider in).

Also, QueryOver<T> is not an option here as we require IQueryable s..

I am using NH 3.1.

For the masses:

We no longer use the Fetch or LINQ, we moved to HQL...

    /// <summary>
    /// Interfaces for Fetch() statements
    /// </summary>

    public interface IFetchingProvider
    {
        IFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector);

        IFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>(IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector);

        IFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector);

        IFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>(IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector);
    }


public class NhFetchingProvider : IFetchingProvider
    {
        public IFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector)
        {
            var fetch = EagerFetchingExtensionMethods.Fetch(query, relatedObjectSelector);
            return new FetchRequest<TOriginating, TRelated>(fetch);
        }

        public IFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>(IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector)
        {
            var fecth = EagerFetchingExtensionMethods.FetchMany(query, relatedObjectSelector);
            return new FetchRequest<TOriginating, TRelated>(fecth);
        }

        public IFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector)
        {
            var impl = query as FetchRequest<TQueried, TFetch>;
            var fetch = EagerFetchingExtensionMethods.ThenFetch(impl.NhFetchRequest, relatedObjectSelector);
            return new FetchRequest<TQueried, TRelated>(fetch);
        }

        public IFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>(IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector)
        {
            var impl = query as FetchRequest<TQueried, TFetch>;
            var fetch = EagerFetchingExtensionMethods.ThenFetchMany(impl.NhFetchRequest, relatedObjectSelector);
            return new FetchRequest<TQueried, TRelated>(fetch);
        }
}

public static IFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector, Func<IFetchingProvider> FetchingProvider)
        {
            return FetchingProvider().Fetch(query, relatedObjectSelector);
        }

Using inner joins with linq in NHibernate isn't supported yet. more info can be found here: https://nhibernate.jira.com/browse/NH-2790


I've added support for it!!

https://www.nuget.org/packages/NHibernate.Linq.InnerJoinFetch

Enjoy!!!

链接地址: http://www.djcxy.com/p/60998.html

上一篇: 流利Nhibernate,参考和太多的查询

下一篇: Nhibernate为获取生成OUTER JOIN