Oliver
Oliver

Reputation: 11597

Automatically updating corresponding collection in NHibernate?

My database has two tables:

Users
    UserId        PK

Likes
    LikeId        PK
    LikedUserId   FK
    LikingUserId  FK

These tables represent user 'likes'. Likes are directional - user A likes user B, but user B does not like user A.

I am mapping with NHibernate like this:

<class name="User" table="Users">
    <id name="UserId">
        <generator class="assigned"></generator>
    </id>

    <idbag name="LikedBy" table="Likes" inverse="true">
        <collection-id column="LikeId" type="guid">
            <generator class="guid.comb"/>
        </collection-id>
        <key column="LikedUserId"/>
        <many-to-many column="LikingUserId" class="User"/>
    </idbag>

    <idbag name="Liking" table="Likes">
        <collection-id column="LikeId" type="guid">
            <generator class="guid.comb"/>
        </collection-id>
        <key column="LikingUserId"/>
        <many-to-many column="LikedUserId" class="User"/>
    </idbag>
</class>

Corresponding to this class:

public class User 
{
    public Guid UserId { get; set; }
    public ICollection<User> LikedBy { get; set; }
    public ICollection<User> Liking { get; set; }
}

This works fine. However, the Liking and LikedBy collections for two different users can get out of sync. For instance:

using (var session = new NHibHelp.OpenSession())
{
    var user1 = session.GetById<User>(id1);
    var user2 = session.GetById<User>(id2);

    int initialCount = user2.LikedBy.Count();

    user1.Liking.Add(user2);
    session.Update(user1);

    int finalCount = user2.LikedBy.Count();

    Assert.AreEqual(initalCount,finalCount); // passes
}

So if I add to the Liking collection of one user, the LikedBy collection of another user is not updated. To have it updated, I need to do Session.Refresh().

This isn't ideal. I'm quite new to NHibernate, so I don't know if there is another solution - is there anything better I can do? For instance, is it possible to map this scenario in such a way that LikedBy is automatically updated when appropriate?

Upvotes: 3

Views: 620

Answers (1)

SHSE
SHSE

Reputation: 2433

You can add a method to the User class that syncs both collections:

public class User 
{
    public Guid UserId { get; set; }
    public ICollection<User> LikedBy { get; set; }
    public ICollection<User> Liking { get; set; }

    public void Like(User user) 
    {
       this.Liking.Add(user);
       user.LikedBy.Add(this);
    }
}

You may also make this collections readonly to an external code:

private ICollection<User> likedBy;
private ICollection<User> liking;

public IEnumerable<User> LikedBy { get { return this.likedBy; } }
public IEnumerable<User> Liking { get { return this.liking; } }

<idbag access="field.camelcase" ... />

Upvotes: 2

Related Questions