Halvard
Halvard

Reputation: 4003

How do I save two equal objects in an NHibernate session?

I have the following object structure (simplified):

MainObject
  Person PersonA
  Person PersonB
Person
  string Name
  Status Status

Basically, my MainObject could hold two Person objects. The Person objects will (for this business case) always be different objects, but the Status object on each Person may refer to the same Status (they may both be in status DocumentsUploaded, for example).

Since I am using Fluent NHibernate I get the following exception when I try to save a MainObject when both Persons have the same Status: a different object with the same identifier value was already associated with the session. This makes sense since both Status objects are the same.

When I have googled the error I have mostly found posts where it turns out someone got the same identifier in their session by mistake (and I want to do it on purpose).

I also considered changing the Status field on Person to an integer, but that feels wrong (un-object oriented, if you will).

The question: Is there any way around this, any way to tell NHibernate that, yes, I know that they have the same identifier, but that I would like to save it anyway? If not, what is the reason this is not possible and what is your suggestion?

In case it matters;

Here is the code in my repository:

public void Save<T>(T entity) where T : DomainEntity
{
    using (var session = _sessionSource.CreateSession())
    {
        using (var transaction = session.BeginTransaction())
        {
            session.SaveOrUpdate(entity);
            transaction.Commit();
        }
    }
}

(MainObject, Person and Status all inherit DomainEntity and everything works fine except for the scenario described above)

Edit: Code for loading

This is the simplified code for loading the Status on each of the Persons on the MainObject:

_mainObject.PersonA.Status = _repository.GetStatus(StatusCode.NotSet);
_mainObject.PersonB.Statys = _repository.GetStatus(StatusCode.NotSet);

This is the simplied code for GetStatus in the repository:

public Status GetStatus(StatusCode statusCode)
{
    return Repository.Query<Status>(x => x.StatusCode == statusCode).FirstOrDefault();
}

And this is the code for Query:

public List<T> Query<T>(Expression<Func<T, bool>> expression) where T : DomainEntity
{
    using (var session = _sessionSource.CreateSession())
    {
        using (var transaction = session.BeginTransaction())
        {
            var result = session.Query<T>().Where(expression);
            transaction.Commit();
            return result.ToList();
        }
    }
}

Thanks in advance!

Upvotes: 3

Views: 984

Answers (1)

fluent
fluent

Reputation: 2403

I believe the problem is the micro management of sessions. If you had one session that covered all of the database transactions I do not believe you would get the issue.

If the project is web service I would suggest that you look at tying the session creation/disposal to the http request.

Upvotes: 2

Related Questions