2012-01-30 5 views
0

Je suis relativement nouveau dans l'utilisation de base de NHibernate. Je me demande si quelqu'un peut me aider à formuler le code pour le scénario suivant:Plusieurs requêtes de jointure et tables de pontage avec NHibernate

Structure de la table

UserProfile

UserProfile_SubTableA_Bridge

SubTableA

UserProfile_SubTableB_Bridge

SubTableB

Je suis en train de construire une requête qui accomplit ceci:

FetchAllNotDeleted(IEnumerable<SubTableB> SelectedA, IEnumerable<SubTableB> SelectedB) 
{ 
    select * from UserProfile 
    left join SubTable1_Bridge A 
    left join SubTable2_Bridge B 
    where 
    A.Id in(SelectedA) 
    OR B.Id in (SelectedB) 

    return Query().Future(); 
} 

Cela semble assez simple sql régulière, mais Je ne sais pas comment formuler cette requête en utilisant NHib. Que dois-je faire si je souhaite ajouter les jointures de manière conditionnelle selon que SelectedA ou SelectedB est nul? Quelque chose comme:

if(selectedA != null) { /* add join and restrictions for A */} 
if(selectedB != null) { /* add join and restrictions for B */} 

J'ai essayé ce qui suit, il est proche, mais il "et" les ensemble au lieu de "ou"

if (selectedA != null) 
{ 
var selectedIds = selectedA.Select(x => x.Id.ToString()).ToList(); 
query.JoinQueryOver(x => x.SubA, JoinType.LeftOuterJoin).And(
     Restrictions.Disjunction().Add(
      Restrictions.In("Id", selectedIds) 
     ) 
    ); 
} 

if (selectedB != null) 
{ 
    var selectedIds = selectedB.Select(x => x.Id.ToString()).ToList(); 
    query.JoinQueryOver(x => x.SubB, JoinType.LeftOuterJoin).And(
      Restrictions.Disjunction().Add(
       Restrictions.In("Id", selectedIds) 
      ) 
     ); 
} 
+0

Je pense que la partie sur laquelle je suis accroché est la partie «OU» de la clause where. Je peux écrire chaque requête séparément, mais je n'arrive pas à les faire faire «l'un ou l'autre» – tjans

+0

Quelle version de NHibernate utilisez-vous? – MonkeyCoder

+0

J'utilise 3.2.0.2001 – tjans

Répondre

0
Sub1Entity sub1 = null; 
Sub1Entity sub2 = null; 

session.QueryOver<UserProfile>() 
    .JoinAlias(up => up.Sub1,() => sub1) 
    .JoinAlias(up => up.Sub2,() => sub2) 
    .Where(Restrictions.Or(
     Restrictions.In(Projections.Property(() => sub1.Id), SelectedA), 
     Restrictions.In(Projections.Property(() => sub2.Id), SelectedB)) 
    .Future(); 

Mise à jour: conditionnellement

var query = session.QueryOver<UserProfile>(); 
Disjunction or = null; 

if(selectedA != null) 
{ 
    Sub1Entity sub1 = null; 
    query = query.JoinAlias(up => up.Sub1,() => sub1) 
    or = (or ?? new Disjunction()).Add(Restrictions.In(Projections.Property(() => sub1.Id), SelectedA)); 
} 

if(selectedB != null) 
{ 
    Sub2Entity sub2 = null; 
    query = query.JoinAlias(up => up.Sub2,() => sub2) 
    or = (or ?? new Disjunction()).Add(Restrictions.In(Projections.Property(() => sub2.Id), SelectedB)); 
} 

if (or != null) 
    query = query.Where(or); 

return query.Future(); 
+0

Est-ce que JoinAlias ​​fait une jointure à gauche? – tjans

+0

jointure interne par défaut, mais vous pouvez ajouter '.JoinAlias' avec' .Left' pour obtenir des jointures à gauche – Firo

+0

Intéressant. Je n'ai jamais vu cette syntaxe auparavant ... donc vous vérifiez s'il y a une disjonction existante et ensuite ajoutez la restriction ... pouvez-vous expliquer votre syntaxe de restriction? Restrictions.In (Projections.Property (() => sub2.Id) spécifiquement: () => sub2.Id – tjans

Questions connexes