Domanda

I've got a bit of code that tries to access same association path twice and they're really same aliases but because I'm using query objects, I have them in two different places and I am not really sure how to get the alias.

May be some code can clear the confusion:

var privateBlogQuery = new BlogQuery()
    .ByUser(1)
    .RemoveHidden()
    .FetchUserDetails();


//<-------- In Blog Query object class: ------>

/// Gets all the private blogs the user has permissions to view
public BlogQuery ByUser(int userId)
{
    var authorisedUsers = null;

    this.Left.JoinQueryOver(r => r.AuthorisedUsers, () => authorisedUsers)
        .Where(r => r.User.Id == userId);

    return this;
}

/// Removes all private blogs user has marked to be hidden
public BlogQuery RemoveHidden()
{
    var authorisedUsers = null;

    this.Left.JoinQueryOver(r => r.AuthorisedUsers, () => authorisedUsers)
        .Where(r => !r.IsHidden);

    return this;
}

/// Loads up details of all users who have permission 
/// to view the private blog
public BlogQuery FetchUserDetails()
{
    var users = null;
    var authorisedUsers = null;

    this.Left.JoinQueryOver(r => r.AuthorisedUsers, () => authorisedUsers)
        .Left.JoinQueryOver(r => r.User, () => users);

    return this;
}

There are times when I'm using all 3 criteria individually and the sql generated is precisely what I need and everything is nice and dandy as long as they are used separately.

Now I need to use them all together, at the same time and nhibernate throws an exception duplicate alias and I changed up the alias on these three functions but then I am greeted with the duplicate association path exeception.

A bit of googling and I learnt that it is a bug in hibernate and I also found a few workarounds on this bug

Trouble is I am using Query objects and hence Query over and I am not really sure how to get the association path / alias here.

So how do I go about this please?

È stato utile?

Soluzione

  • make authorisedUsers a membervariable of BlogQuery and use a marker/flag to know if ByUser and RemoveHidden should do the Join
  • use JoinAlias

example

AuthorisedUser authorisedUser;
bool authorisedUsersJoined;

public BlogQuery RemoveHidden()
{
    if (!authorisedUsersJoined)
        this.Left.JoinAlias(r => r.AuthorisedUsers, () => authorisedUser);

    this.Where(() => !authorisedUser.IsHidden);

    return this;
}

FetchUserDetails is mutual exclusive with the other two because filtering on an association prevents NH from initializing the association. You'll need to subquery with the filter and query the resulting Ids and initialize then.

/// Loads up details of all users who have permission 
/// to view the private blog
public BlogQuery FetchUserDetails()
{

    this.Query = QueryOver.Of<Blog>()
        .WhereRestrictionOn(b => b.Id).IsIn(this.Query.Select(b => b.Id))
        .Fetch(r => r.AuthorisedUsers).Eager
            .ThenFetch(au => au.User).Eager;

    return this;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top