开发者

Mapping interface on multiple hierarchies with NHibernate

Given 2 classes that are not related, one of which is a member of another inheritance hierarchy, how can I map an interface on both of the classes so that I can query against the interface and have the appropriate concrete type returned? E.g.

public abstract class Survey 
{ 
    public Guid Id { get; private set; } 
} 

public class InviteOnlySurvey : Survey 
{ 
    public ICollection<Invite> Invites { get; private set; } 
} 

public class Invite : ISurveyGateway 
{ 
    public Guid Id { get; private set; } 
    public InviteOnlySurvey Survey { get; private set; } 
} 

public class SharedSurvey : Survey, ISurveyGateway { ... } 

public interface ISurveyGateway 
{ 
    Guid Id { get; } 
} 

Currently I have mapped Survey, InviteOnlyLiveSurvey and SharedLiveSurvey using table per class hierarchy and now I am trying to figure out how to map ISurveyGateway so that I can query against it and have NHibernate find the matching entity ( Invite or SharedLiveSurvey ) seamlessly. ISurveyGateway instances are effectively readonly as all the remaining persistence concerns are managed through the mappings for SharedSurvey and Invite.

If I remove the ISurveyGateway interface from either SharedSurvey or Invite, I can query and retrieve ISurveyGateway instances via NHibernate, but as soon as I apply the interface to 2 different hierarchies I get an exception with the message "Ambiguous pers开发者_StackOverflow社区ister for ISurveyGateway implemented by more than one hierarchy" (which is expected - I just don't know how to make it work).


The answer with QueryOver and FutureValue works, but here is an even simpler solution:

public ISurveyGateway FindSurveyGatewayById( Guid id )
{
  var surveyGateway = session
     .QueryOver<ISurveyGateway>
     .Where( s => s.Id == id )
     .SingleOrDefault<ISurveyGateway>();
  return surveyGateway;
}

But you should be careful, your Id should be a Guid. If it's not the case you may get multiple responses...


Given that both Invite and SharedSurvey are already mapped and being used and because the Ids are Guids which ensures that there will not be a SharedSurvey and an Invite with the same Id ( with a fairly high degree of certainty ) I found a far simpler approach.

public ISurveyGateway FindSurveyGatewayById( Guid id )
{
  var sharedSurveyGateway = session.QueryOver<SharedSurvey>
    .Where( s => s.Id == id )
    .FutureValue<ISurveyGateway>();

  var inviteGateway = session.QueryOver<Invite>
    .Where( i => i.Id == id )
    .FutureValue<ISurveyGateway>();

  return sharedSurveyGateway.Value ?? inviteGateway.Value;
}

There are some downsides with this - the main one being that this query now has to be extended for every ISurveyGateway that is added to the system, but for now it does the job with the least complexity and with reasonable performance.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜