Search code examples
asp.netlinqnhibernatefluent-nhibernatenhibernate-mapping

NHibernate - Eager load one-to-many relationship on the basis of type column


I need to eager load three one-to-many relationship from a same table to other three tables . Following is the ERD of my table:

enter image description here

ProcessActionLog is the table that has three one-to-many relationship with ProcessActionEmail, ProcessActionInterviewFeedback and ProcessActionNotesInfo tables on the basis of ProcessActionType column that will contain the name of the column following is my mappings of these tables:

1) ProcessActionLog Table Maping:

class ProcessActionLogMap : ClassMap<ProcessActionLog>
    {
        public ProcessActionLogMap()
        {
            //Rest of mappings//
            HasMany(x => x.ProcessActionEmail).Cascade.SaveUpdate().Inverse();
            HasMany(x => x.ProcessActionInterviewFeedback).Cascade.SaveUpdate().Inverse();
            HasMany(x => x.ProcesssActionNotesInfo).Cascade.SaveUpdate().Inverse();
        }

2) ProcessActionEmailMapping:

class ProcessActionEmailMap : ClassMap<ProcessActionEmail>
    {
        public ProcessActionEmailMap()
        {
            //rest of mappings//
            References(x => x.ProcessActionLog, "ProcessActionLogId");
        }
    }

3) ProcessActionInterviewFeedback Mapping:

class ProcessActionInterviewFeedbackMap : ClassMap<ProcessActionInterviewFeedback>
    {
        public ProcessActionInterviewFeedbackMap()
        {
            //Rest of mappings//
            References(x => x.ProcessActionLog, "ProcessActionLogId");
        }
    }

4) ProcessActionNotesInfo

class ProcessActionNotesInfoMap : ClassMap<ProcessActionNotesInfo>
    {
        public ProcessActionNotesInfoMap()
        {
            //Rest of mappings//
            References(x => x.ProcessActionLog, "ProcessActionLogId");
        }
    }

Now I have tried following query in order to eager load all the three relationships:

 public IList<ProcessActionLog> FetchUserSpecificProcessActionLogs(int UserId)
        {
            return _session.Query<ProcessActionLog>()
                            .Where(x => x.MasterUser.Id == UserId)
                            .Fetch(x => x.ProcessActionEmail)
                            .Fetch(x => x.ProcessActionInterviewFeedback)
                            .Fetch(x => x.ProcesssActionNotesInfo)
                            .ToFuture().ToList<ProcessActionLog>();
        }

but this is giving me following error:

Cannot simultaneously fetch multiple bags. 

Kindly help me either to fix this issue or advise any other method in which I can eager load the entities using the processActionType column of ProcessActionLog Table. Thank you.


Solution

  • Finally, solved the issue by using ISet instead of IList in mappings now my code is as following:

    ProcessActionLog Entity

        public class ProcessActionLog
        {
            /// <summary>
            /// Process Action Emails 
            /// </summary>
            private ISet<ProcessActionEmail> _ProcessActionEmail { get; set; }
            /// <summary>
            /// Process Action Interview Feedbacks
            /// </summary>
            private ISet<ProcessActionInterviewFeedback> _ProcessActionInterviewFeedback { get; set; }
            /// <summary>
            /// Process action notes info
            /// </summary>
            private ISet<ProcessActionNotesInfo> _ProcessActionNotesInfo { get; set; }
            /// <summary>
            /// Is process action email
            /// </summary>
            public virtual bool IsProcessActionEmail
            {
                get { return ProcessActionType == ProcessActionType.ProcessActionEmail; }
            }
            /// <summary>
            /// Is process action interview feedback
            /// </summary>
            public virtual bool IsProcessActionInterviewFeedback
            {
                get { return ProcessActionType == ProcessActionType.ProcessActionInterviewFeedback; }
            }
            /// <summary>
            /// Is process action notes info
            /// </summary>
            public virtual bool IsProcessActionNotesInfo
            {
                get { return ProcessActionType == ProcessActionType.ProcessActionNotesInfo; }
            }
            /// <summary>
            /// Process Action Log setter and getter
            /// </summary>
            public virtual ISet<ProcessActionEmail> ProcessActionEmail
            {
                get { return (IsProcessActionEmail ? _ProcessActionEmail : null); }
                set { _ProcessActionEmail = value; }
            }
            /// <summary>
            /// Process Action Interview Feedback setter and getter
            /// </summary>
            public virtual ISet<ProcessActionInterviewFeedback> ProcessActionInterviewFeedback
            {
                get { return (IsProcessActionInterviewFeedback ? _ProcessActionInterviewFeedback : null); }
                set { _ProcessActionInterviewFeedback = value; }
            }
            /// <summary>
            /// Process Action Notes info setter and getter
            /// </summary>
            public virtual ISet<ProcessActionNotesInfo> ProcessActionNotesInfo
            {
                get { return (IsProcessActionNotesInfo ? _ProcessActionNotesInfo : null); }
                set { _ProcessActionNotesInfo = value; }
            }
        }
    

    ProcessActionEmail Entity

    public class ProcessActionEmail
    {
        //Rest of the attributes
    
        /// <summary>
        /// Process Action log of this particular email
        /// </summary>
        public virtual ProcessActionLog ProcessActionLog { get; set; }
    

    ProcessActionInterviewFeedback Entity

    public class ProcessActionInterviewFeedback 
    {
        /// <summary>
        /// Process Action Log
        /// </summary>
        public virtual ProcessActionLog ProcessActionLog { get; set; }
    }
    

    ProcessActionLog Mapping

     class ProcessActionLogMap : ClassMap<ProcessActionLog>
        {
            public ProcessActionLogMap()
            {
                Id(x => x.Id);
                Map(x => x.LogName).Length(100).Not.Nullable();
                Map(x => x.ProcessActionType).CustomType<Int32>().Not.Nullable();
                Map(x => x.CreatedAt).CustomType<DateTime>().Not.Nullable();
                References(x => x.MasterUser).Column("UserId");
                References(x => x.Process).Column("ProcessId");
                References(x => x.SystemUser).Column("CreatedBy");
                References(x => x.Task).Column("TaskId").Nullable();
                HasMany(x => x.ProcessActionEmail).Cascade.SaveUpdate().Inverse();
                HasMany(x => x.ProcessActionInterviewFeedback).Cascade.SaveUpdate().Inverse();
                HasMany(x => x.ProcessActionNotesInfo).Cascade.SaveUpdate().Inverse();
            }
        }
    

    And the query remains the same as was in the question.