2010-09-09 10 views
0

J'ai un peu un scénario impair où j'ai une table qui référence une vue qui contient des lignes qui sont spécifiques à l'utilisateur. La vue a un ID de ligne unique, mais elle n'est jamais utilisée pour référencer l'élément. Au lieu de cela, une valeur unique est dérivée d'une combinaison d'un ID client, d'un ID utilisateur et d'une clé d'objet.Les filtres ne sont pas appliqués pour la référence plusieurs-à-un

public BarMap() 
    { 
     Table(DatabaseObject.UserBars); 

     Id(x => x.Id, "Resource_Id"); 

     Map(x => x.ClientId, "Client_Id"); 
     Map(x => x.UserId, "User_Id"); 

     Map(x => x.Key, "Bar_Key") 
      .Length(10); 
     Map(x => x.Name, "Bar_Name") 
      .Length(255); 

J'ai un filtre appliqué à la classe qui devrait coup de pied dans la clause WHERE en fonction de l'utilisateur actuel et le contexte client. Maintenant, en pratique, je vois ces filtres s'appliquent lorsque j'essaie de récupérer une barre directement. Toutefois, lorsque je récupère un objet nommé Foo qui référence un objet Bar, les filtres sont ignorés dans un appel SELECT secondaire.

public class FooMap : ClassMap<Foo> 
{ 
    public FooMap() 
    { 
     Table(DatabaseObject.Foos); 

     References<Bar>(x => x.Bar, "BarId") 
      .PropertyRef(x => x.Key) 
      .Cascade.None() 
      .Fetch.Join() 
      .NotFound.Exception(); 

Basé sur ce qui précède, vous attendre à ce que Foo aurait exécuterait JOIN pour hydrater l'objet bar, mais il semble sauter et insister sur la récupération d'un objet Foo. Je soupçonne que l'appel SELECT secondaire se produit parce que la bibliothèque NH tente de récupérer l'objet en fonction d'une valeur unique de la clé (dans le journal

Loader.Loader - SELECT this_.Id as Id12_2_, this_.ClientId as ClientId12_2_, this_.BarId as BarId12_2_, Foo1_.Id as Id13_0_, Foo1_.ClientId as ClientId13_0_, Foo1_.Name as Name13_0_, Bar2_.Resource_Id as Resource1_4_1_, Bar2_.Client_Id as Client7_4_1_, Bar2_.User_Id as User8_4_1_, Bar2_.Bar_Key as Bar9_4_1_, Bar2_.Bar_Name as Bar10_4_1_ FROM Foos this_ inner join FooSchedules Foo1_ on this_.ScheduleId=Foo1_.Id inner join User_Bars Bar2_ on this_.BarId=Bar2_.Bar_Key and (Bar2_.Client_Id = :p0 OR Bar2_.Client_Id IS NULL) and Bar2_.User_Id = :p1 WHERE (Foo1_.ClientId = :p2 OR Foo1_.ClientId IS NULL) and (this_.ClientId = :p3 OR this_.ClientId IS NULL) AND Foo1_.Name = :p4 and Bar2_.Bar_Key = :p5 and Bar2_.Client_Id = :p6 and Bar2_.User_Id = :p7 
Loader.Loader - processing result set 
Loader.Loader - result set row: 0 

Je peux voir ici, il a chargé le bar, mais il didn « t hydrater pour une raison ??

Loader.Loader - result row: EntityKey[Core.Domain.FooSchedule#2929992], EntityKey[Core.Domain.Bar#470090], EntityKey[Core.Domain.Foo#3211664] 
Loader.Loader - Initializing object from DataReader: [Core.Domain.FooSchedule#2929992] 
Loader.Loader - Initializing object from DataReader: [Core.Domain.Foo#3211664] 
Loader.Loader - done processing result set (1 rows) 
Loader.Loader - total objects hydrated: 2 
Engine.TwoPhaseLoad - resolving associations for [Core.Domain.FooSchedule#2929992] 
Engine.Loading.LoadContexts - creating collection wrapper:[Core.Domain.FooSchedule.Foos#2929992] 
Engine.TwoPhaseLoad - done materializing entity [Core.Domain.FooSchedule#2929992] 
Engine.TwoPhaseLoad - resolving associations for [Core.Domain.Foo#3211664] 
Engine.Loading.LoadContexts - creating collection wrapper:[Core.Domain.Foo.Items#3211664] 

Voici où il fait une tentative de re-charger la barre, mais ne comprend pas les filtres amenant à revenir plusieurs lignes/sauter ....

Loader.Entity.AbstractEntityLoader - Static select for entity Core.Domain.Bar: SELECT Bar0_.Resource_Id as Resource1_4_0_, Bar0_.Client_Id as Client7_4_0_, Bar0_.User_Id as User8_4_0_, Bar0_.Bar_Key as Bar9_4_0_, Bar0_.Bar_Name as Bar10_4_0_ FROM User_Bars Bar0_ WHERE Bar0_.Bar_Key=? 
Loader.Loader - loading entity: [Core.Domain.Bar#ABFDBC01] 
Engine.QueryParameters - BindParameters(Named:NHibernate.Type.StringType) ABFDBC01 -> [0] 
Loader.Loader - SELECT Bar0_.Resource_Id as Resource1_4_0_, Bar0_.Client_Id as Client7_4_0_, Bar0_.User_Id as User8_4_0_, Bar0_.Bar_Key as Bar9_4_0_, Bar0_.Bar_Name as Bar10_4_0_ FROM User_Bars Bar0_ WHERE Bar0_.Bar_Key=:p0 
Loader.Loader - processing result set 

J'aimerais retravailler la vue Bar mais les contraintes de temps ne le permettront pas à moins que ce ne soit absolument nécessaire. Des idées sur la façon d'obtenir des filtres à appliquer? Ou y a-t-il des conseils sur la façon de faire des références d'objets spécifiques au contexte?

J'ai trouvé une référence sur le côté JBoss qu'Hibernate aurait aussi pu avoir avec un potentially related design issue. En regardant dans le code source NHibernate le problème semble centrer autour EntityJoinWalker:

SqlStringBuilder whereCondition = WhereString(Alias, uniqueKey, batchSize) 
    //include the discriminator and class-level where, but not filters 
    .Add(persister.FilterFragment(Alias, new CollectionHelper.EmptyMapClass<string, IFilter>())); 

Si je change à ce que tout fonctionne bien, mais je ne suis pas sûr de ce que l'impact du changement est et le commentaire n » t vraiment indiquer pourquoi les filtres devraient être exclus.

SqlStringBuilder whereCondition = WhereString(Alias, uniqueKey, batchSize) 
    .Add(persister.FilterFragment(Alias, enabledFilters)); 

Aide ?!

+0

L'idée originale est venue du wiki NHForge.org en termes d'utilisation des filtres sur context- objets conscients. Il semble que dans le cas des relations, les filtres ne s'appliquent pas. Vous ne savez pas comment gérer l'association d'un objet contextuel maintenant. : S –

Répondre

0

Résolu en appliquant le filtrage dans la classe de carte (nouveau NH 2.1.2 par les regards de celui-ci):

Where("Client_Id = :clientFilter.clientId AND User_Id = :userFilter.userId");