views:

128

answers:

1

I am having an odd error when using Fluent NHibernate. I have an entity object called Module that is my "aggregate root" if you will. I created and tested my mappings for the Module class and the various related classes and tried creating a Module with all of its fields filled out and saving it. This worked correctly.

My problem is when I try to retrieve the objects from the database. The Module object comes back just fine, however any of the collections it contains are all empty even though I see the objects in the database tables!! I could really use a hand on this one, I hope somone can help!

edit: added the code for BuildDeriveModule below.

Here is my test:

var dei1 = BuildDeriveModule();

var sessionSource = Injector.Resolve<ISessionSource>();

using (var session = sessionSource.CreateSession())
{
    using (var transaction = session.BeginTransaction())
    {
     session.Save(dei1);
     transaction.Commit();
    }
}

Module item = null;
using (var session = sessionSource.CreateSession())
{
   item = session
       .CreateCriteria(typeof(Module))
       .Add(Restrictions.Eq("ModuleId", dei1.ModuleId))
       .UniqueResult<Module>();

    Assert.Equal<Module>(dei1, item);
    Assert.Equal<int>(4, item.Variables.Count);
}

My Module class looks like this: (Note: Entity comes from FluentNHibernate.Data.Entity)

 public class Module : Entity, IEntity
    {
        public Module()
        {
            Variables = new HashedSet<ModuleVariable>();
        }

        public virtual string ModuleId
        {
            get;
            set;
        }

        public virtual ISet<ModuleVariable> Variables
        {
            get; 
            set;
        }

        public virtual Variable StratumVariable
        {
            get;
            set;
        }

        public virtual Stratum DefaultStratum
        {
            get;
            set;
        }

        public virtual ISet<Stratum> OptionalStrata
        {
            get;
            set;
        }

        public virtual DateTime LastUpdated
        {
            get;
            set;
        } 

        #region Override Methods

        public override string ToString()
        {
            return this.ModuleId;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;

            var other = obj as Module;

            if (other == null) return false;

            if (other.ModuleId != this.ModuleId) return false;

            return true;
        }

        public override int GetHashCode()
        {
            return ModuleId.GetHashCode();
        } 

        #endregion
    }

And my Mapping looks like this:

public class ModuleMap : ClassMap<Module>
{
    public ModuleMap()
    {
        Id(x => x.Id);
        Version(x => x.LastUpdated);
        Map(x => x.ModuleId)
            .Unique()
            .Not.Nullable();
        HasMany<ModuleVariable>(x => x.Variables)
            .Inverse()
            .Cascade.SaveUpdate();
        References<Variable>(x => x.StratumVariable)
            .Not.Nullable()
            .Cascade.SaveUpdate();
        References<Stratum>(x => x.DefaultStratum)
            .Not.Nullable()
            .Cascade.SaveUpdate();
        HasMany<Stratum>(x => x.OptionalStrata)
            .Inverse()
            .Cascade.SaveUpdate();
    }
}

BuildDeriveModule's code:

private Module BuildDeriveModule() { var pp01 = new Relation { RelationId = "PP01" };

        var hh01 = new Relation
        {
            RelationId = "HH01"
        };

        var stdei1 = new Variable
        {
            VariableId = "STDEI1",
            Relation = pp01
        };

        var frameId = new Variable
        {
            VariableId = "FRAME_ID",
            Relation = pp01
        };

        var persno = new Variable
        {
            VariableId = "PERSNO",
            Relation = pp01
        };

        var hp = new Driver
        {
            Name = "HP",
            Phase = 1
        };

        hp.KeyVariables.Add(frameId);
        hp.KeyVariables.Add(persno);

        var r2p1 = new Variable
        {
            VariableId = "R2P1",
            Relation = pp01
        };

        var age = new Variable
        {
            VariableId = "AGE",
            Relation = pp01
        };

        var marst = new Variable
        {
            VariableId = "MARST",
            Relation = pp01
        };

        var doctp = new Variable
        {
            VariableId = "DOCTP",
            Relation = hh01
        };

        pp01.AddVariable(stdei1);
        pp01.AddVariable(r2p1);
        pp01.AddVariable(age);
        pp01.AddVariable(marst);
        hh01.AddVariable(doctp);

        var defaultStratum = new Stratum
        {
            Number = -1,
            Driver = hp
        };

        var dei1 = new Module
        {
            ModuleId = "DEI1",
            StratumVariable = stdei1,
            DefaultStratum = defaultStratum
        };

        var mv_r2p1 = new ModuleVariable
        {
            ModuleId = dei1,
            VariableId = "R2P1",
            UploadId = r2p1,
            DownloadId = r2p1,
            HasSubunits = true
        };

        var mv_age = new ModuleVariable
        {
            ModuleId = dei1,
            VariableId = "AGE",
            UploadId = age,
            DownloadId = age,
            HasSubunits = true
        };

        var mv_marst = new ModuleVariable
        {
            ModuleId = dei1,
            VariableId = "MARST",
            UploadId = marst,
            DownloadId = marst,
            HasSubunits = true
        };

        var mv_doctp = new ModuleVariable
        {
            ModuleId = dei1,
            VariableId = "DOCTP",
            UploadId = doctp,
            DownloadId = doctp,
            HasSubunits = false
        };

        dei1.AddVariable(mv_r2p1);
        dei1.AddVariable(mv_age);
        dei1.AddVariable(mv_marst);
        dei1.AddVariable(mv_doctp);

        return dei1;
    }
A: 

OK, I think I got it to work. I removed the .Inverse() from thins line

HasMany<ModuleVariable>(x => x.Variables)
            .Inverse()
            .Cascade.SaveUpdate();

in ModuleMap and the unit test worked. I'm not quite sure why though, so if anyone can point out that out it would be appreciated.

Jeffrey Cameron