Reconciling persistent collections

12 views
Skip to first unread message

Michael W Powell

unread,
Jun 6, 2025, 11:29:51 PMJun 6
to Fluent NHibernate
Hello,

Now that I feel I have sorted most of the major concerns and but for a couple of lingering desires for reference conventons and what not...

Now to one burning question, how to handle synchronizing with persistent collections. What do I mean by that.

I am pretty confident that new instances would simply be inserted and existing instances be updated, as per usual.

But what happens with non-existent instances. That have been removed from the loaded and/or newly attached instance, and that still exist in the persistent store?

The issue I was findingwith EF, for instance, these instances required manual intervention, or I had not discovered the EF policy making that issue transparently resolved at the ORM level.

Does it make sense? Much appreciated any insights.

Best, thank you,

Michael W. Powell

Michael W Powell

unread,
Jun 7, 2025, 12:16:40 AMJun 7
to Fluent NHibernate
I should also mention to clarify further, I have the use case where the instances I load are effectively all detached from any session. I do this intentionally as it feeds my WPF application. Then when I am ready to save after some changes have been made to the instances and constituent collections, I would reattach all to a new session. There are moments when that happens when the composition of collections would then be different. So there needs to be some reconciling between the two. I had to take some steps in countermeasure with EF apparently; not sure if FNH is any more or less transparent under those conditions.

Thanks!

Michael W Powell

unread,
Jun 7, 2025, 6:38:38 PMJun 7
to Fluent NHibernate
Following up... I do not think there is a simple solution for this.

I have table A and B and a joining table C, with adjoining member collections in both A and B having many C instances held there.

I load in the domain properly and detach, I have the instances and then let the ISession etc fall out of scope and dispose.

I am removing an existing C relationship there detatched. I see the correct bidirectional logic happening, at least as far as the domain is concerned.

Then I feed these instances back into a new session and am trying to run either Save or SaveOrUpdate and getting this error.

NHibernate.PropertyValueException: 'not-null property references a null or transient value WhalleyBotEnhanced.Console.Spike.Models.MyRoster.Team'. That I know of, there are no database requests happening during this time, things are entirely ORM bound at that moment.

Let's talk practical model terms. For brevity, obviously there are backing fields and such invovled, but for sake of conversation, this is the desired shape.

class League
{
    IList<Team> Teams { get; set; }
    IList<Player> Players { get; set; }
}

class Team
{
    League League { get; set; }
    IList<Roster> Rosters { get; set; }
}

class Player
{
    League League { get; set; }
    IList<Roster> Rosters { get; set; }
}

class Roster
{
    bool IsStarter { get; set; }
    Rank Rank { get; set; }
    Team Team { get; set; }
    Player Player { get; set; }
}

Obviously there is business logic there, observable collections wrapping the IList<T> indirectly, allowing NH to engage with the mapped properties.

In my detached sequence I am doing exactly this, which would not be atypical of a given scenario.

if (leagues.FirstOrDefault() is League league
    && league.Players.FirstOrDefault() is Player player
    && player.Rosters.FirstOrDefault() is Roster roster)
{
    var team = roster.Team;

    // Remove one player from the team, observable collection responds with the player-team side.
    team.ObservableRosters.Remove(roster);

    // Generate a new player and add to leage then team roster.
    player = new() { };

    league.ObservablePlayers.Add(player);

    roster = new() { Player = player, IsStarter = true };
    team.ObservableRosters.Add(roster);
}

So there are some mixed persistent and transient instances going on here, dirties a collection in the process, etc.

I save the objects at the league level.

Do I need to re-query and compare the tree side by side? Then at least start by deleting instances which would be orphaned or should be deleted, i.e. the Roster instance. I did something similar with EF actually.

Obviously what I am doing with this experiment is not working, so I need to do something else different. What I have detached and feeding the UI and asynchronous processes, is in one state. And will always need to potentially be reconciled with the database state in some way.

Any clues around  this sort of behavior would be grand.

I did scan over the manupulating data chapter, particularly on detached data, but I'm not sure it was especially helpful. I tried what it suggested and got these errors.


From other forums, one thought is to restructure Team and Roster, and since Players are not technically required to join a team, having a team null instance after a sort to help with that business logic.

Honestly right now that thought may be growing on my regardless, but might like to maintain the Roster table, as there are other bits of details that only make sense for that, not for player per se; i.e. Rank, IsStarter, for instance.

Best.

Michael W. Powell
Reply all
Reply to author
Forward
0 new messages