This is possibly a case for ghostbusters! http://nhforge.org/blogs/nhibernate/archive/2008/10/20/how-test-your-mappings-the-ghostbuster.aspx http://jfromaniello.blogspot.com/2010/02/nhibernate-ghostbuster-version-11.html
John Davidson On Thu, Nov 4, 2010 at 8:43 AM, Michael Delva <[email protected]> wrote: > Hello everybody, > > I hope this post won't be too long, and I'll be able to correctly > explain this problem which makes me go nuts. > > I have an entity hierarchy with teams, which have TeamRosters, > containing a reference to Players (with further informations). > > I have some Matches, which each one having a reference to the both > teams competing, and a reference to MatchRosters (one for each team), > containing the players from each team, who will play the match. > > TeamRoster and MatchRoster both derive from an abstract Roster entity. > > I have the following test: > > [Fact] > public void DeleteEntity_DoesntDeleteTeam_IfTeamHasMatches() > { > var player = new Player("M", "D", 10, Sex.Male); > > Kernel.Get<IPlayersRepository>().Save(player); > > var team = new Team("JAO", Sex.Male); > team.DefaultRoster.AddPlayer(player); > > Kernel.Get<ITeamsRepository>().Save(team); > > var otherTeam = new Team("USVO", Sex.Male); > Kernel.Get<ITeamsRepository>().Save(otherTeam); > > var match = new Match() > { > Name = "Foo", > Location = "Bar", > HomeTeam = team, > RoadTeam = otherTeam > }; > > Kernel.Get<IMatchesRepository>().Save(match); > > var viewModel = Kernel.Get<TeamsManagementViewModel>(); > > viewModel.DisplayEntity(new DisplayEntityInfosMessage(1)); > > var dbQuery = > viewModel.DeleteEntity().Enumerate().Next<DbQueryResult>(); > > dbQuery.DoQuery(); > > Assert.Equal(2, > Kernel.Get<ISession>().QueryOver<Team>().RowCount()); > } > > Here are the SQL commands before I create viewModel: > > NHibernate: INSERT INTO Players (Sex, FirstName, LastName, > DefaultNumber, Visible, DefaultPosition_id, Id) VALUES (@p0, @p1, @p2, > @p3, @p4, @p5, @p6);@p0 = 0 [Type: Int32 (0)], @p1 = 'M' [Type: String > (0)], @p2 = 'D' [Type: String (0)], @p3 = 10 [Type: Int32 (0)], @p4 = > True [Type: Boolean (0)], @p5 = NULL [Type: Int32 (0)], @p6 = 1 [Type: > Int32 (0)] > NHibernate: INSERT INTO Teams (Sex, Name, Visible, Location, Id) > VALUES (@p0, @p1, @p2, @p3, @p4);@p0 = 0 [Type: Int32 (0)], @p1 = > 'JAO' [Type: String (0)], @p2 = True [Type: Boolean (0)], @p3 = NULL > [Type: String (0)], @p4 = 1 [Type: Int32 (0)] > NHibernate: INSERT INTO "Roster" (Team_id, Id) VALUES (@p0, @p1);@p0 = > 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)] > NHibernate: INSERT INTO "TeamRoster" (IsDefault, Name, Team_id, > Roster_id) VALUES (@p0, @p1, @p2, @p3);@p0 = True [Type: Boolean (0)], > @p1 = 'Default' [Type: String (0)], @p2 = 1 [Type: Int32 (0)], @p3 = 1 > [Type: Int32 (0)] > NHibernate: INSERT INTO "PlayerInTeam" (PlayerNumber, Player_id, > Position_id, Roster_id, Id) VALUES (@p0, @p1, @p2, @p3, @p4);@p0 = 10 > [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)], @p2 = NULL [Type: Int32 > (0)], @p3 = 1 [Type: Int32 (0)], @p4 = 1 [Type: Int32 (0)] > NHibernate: INSERT INTO Teams (Sex, Name, Visible, Location, Id) > VALUES (@p0, @p1, @p2, @p3, @p4);@p0 = 0 [Type: Int32 (0)], @p1 = > 'USVO' [Type: String (0)], @p2 = True [Type: Boolean (0)], @p3 = NULL > [Type: String (0)], @p4 = 2 [Type: Int32 (0)] > NHibernate: INSERT INTO "Roster" (Team_id, Id) VALUES (@p0, @p1);@p0 = > 2 [Type: Int32 (0)], @p1 = 2 [Type: Int32 (0)] > NHibernate: INSERT INTO "TeamRoster" (IsDefault, Name, Team_id, > Roster_id) VALUES (@p0, @p1, @p2, @p3);@p0 = True [Type: Boolean (0)], > @p1 = 'Default' [Type: String (0)], @p2 = 2 [Type: Int32 (0)], @p3 = 2 > [Type: Int32 (0)] > NHibernate: INSERT INTO "Roster" (Team_id, Id) VALUES (@p0, @p1);@p0 = > 1 [Type: Int32 (0)], @p1 = 3 [Type: Int32 (0)] > NHibernate: INSERT INTO "MatchRoster" (Match_id, Roster_id) VALUES > (@p0, @p1);@p0 = NULL [Type: Int32 (0)], @p1 = 3 [Type: Int32 (0)] > NHibernate: INSERT INTO "PlayerInTeam" (PlayerNumber, Player_id, > Position_id, Roster_id, Id) VALUES (@p0, @p1, @p2, @p3, @p4);@p0 = 10 > [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)], @p2 = NULL [Type: Int32 > (0)], @p3 = 3 [Type: Int32 (0)], @p4 = 2 [Type: Int32 (0)] > NHibernate: INSERT INTO "Roster" (Team_id, Id) VALUES (@p0, @p1);@p0 = > 2 [Type: Int32 (0)], @p1 = 4 [Type: Int32 (0)] > NHibernate: INSERT INTO "MatchRoster" (Match_id, Roster_id) VALUES > (@p0, @p1);@p0 = NULL [Type: Int32 (0)], @p1 = 4 [Type: Int32 (0)] > NHibernate: INSERT INTO Matches (Name, Date, Location, > Championship_id, HomeTeam_id, RoadTeam_id, HomeRoster_id, > RoadRoster_id, Id) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, > @p8);@p0 = 'Foo' [Type: String (0)], @p1 = 4/11/2010 12:56:00 [Type: > DateTime (0)], @p2 = 'Bar' [Type: String (0)], @p3 = NULL [Type: Int32 > (0)], @p4 = 1 [Type: Int32 (0)], @p5 = 2 [Type: Int32 (0)], @p6 = 3 > [Type: Int32 (0)], @p7 = 4 [Type: Int32 (0)], @p8 = 1 [Type: Int32 > (0)] > NHibernate: UPDATE "MatchRoster" SET Match_id = @p0 WHERE Roster_id = > @p1;@p0 = 1 [Type: Int32 (0)], @p1 = 3 [Type: Int32 (0)] > NHibernate: UPDATE "MatchRoster" SET Match_id = @p0 WHERE Roster_id = > @p1;@p0 = 1 [Type: Int32 (0)], @p1 = 4 [Type: Int32 (0)] > > The key property here is match.HomeRoster.Players, which, after the > match is saved, has 1 player, as it should. > > The problem comes after I create the viewModel: > > I ask it to load the team from the database, with DisplayEntity, which > consists in a call to Repository.ReGet: > > public TEntity ReGet(int id) > { > return Transact(() => > { > var entity = Get(id); > > Session.Evict(entity); > Session.Load(entity, id); > > return entity; > }); > } > > When I get the entity back in my view-model, there is not only one > player in Match.HomeRoster.Players, but 2, the latter being a > transient player. Which of course throws the following exception: > > NHibernate.PropertyValueException: not-null property references a null > or transient value Emidee.CommonEntities.PlayerInTeam.Roster. > > Do you have any ideas about why I have this problem? > > Thanks in advance > > PS: Here are the mappings of the various entities used in this test, > with FluentNH: > > public class TeamMap : ClassMap<Team> > { > public TeamMap() > { > Id(t => t.Id) > .GeneratedBy.Increment(); > > HasMany(t => t.Rosters) > .AsSet() > .Inverse() > .Cascade.AllDeleteOrphan(); > > HasMany(t => t.MatchesAtHome) > .Inverse(); > > HasMany(t => t.MatchesOnRoad) > .Inverse(); > } > } > > public class MatchMap : ClassMap<Match> > { > public MatchMap() > { > Id(p => p.Id) > .GeneratedBy.Increment(); > > References(m => m.HomeTeam) > .Not.Nullable(); > > References(m => m.RoadTeam) > .Not.Nullable(); > > References(m => m.HomeRoster) > .Cascade.SaveUpdate(); > > References(m => m.RoadRoster) > .Cascade.SaveUpdate(); > } > } > > public class RosterMap : ClassMap<Roster> > { > public RosterMap() > { > Id(tr => tr.Id) > .GeneratedBy.Increment(); > > References(tr => tr.Team) > .Not.Nullable(); > > HasMany(r => r.Players) > .Inverse() > .Cascade.AllDeleteOrphan(); > } > } > > public class MatchRosterMap : SubclassMap<MatchRoster> > { > public MatchRosterMap() > { > References(mr => mr.Match); > } > } > > -- > You received this message because you are subscribed to the Google Groups > "nhusers" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]<nhusers%[email protected]> > . > For more options, visit this group at > http://groups.google.com/group/nhusers?hl=en. > > -- You received this message because you are subscribed to the Google Groups "nhusers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/nhusers?hl=en.
