Traitée Where successifs

  • jeudi 16 février 2012 11:02
     
      A du code

    Je rencontre un problème avec des filtres "where" qui quand appliques successivement retournent un dataset vide mais fonctionnent parfaitement quand ils sont combinées

    Ceci fonctionne :

    Dim Tlog = From L In db.MyLogs Select L
    Dim s_level  As String = "warning"
    Dim s_source As String = "web"
    
    Tlog = Tlog.Where(Function(x) x.Level = s_level).Where(Function(x) x.Source =  s_source)
    

    Cala non :

    Tlog = Tlog.Where(Function(x) x.Level = s_level)
    Tlog = Tlog.Where(Function(x) x.Source =  s_source)

    N’étant pas expert en la matière je ne sais pas si c’est normal ou pas. Pourriez-vous m’éclairer.

    En vous remerciant d’avance


    BB

Toutes les réponses

  • jeudi 16 février 2012 12:13
     
     

    Bonjour,

    J'ai fait un test mais je ne vois aucune différence dans le SQL généré. Utiliser SQL Server Profiler ou éventuellement (si vous utiliser un "ObjectContext") :

    Debug.WriteLine(CType(Tlog,System.Data.Objects.ObjectQuery).ToTraceString)

    Pour l'instant j'ai l'impression que le problème est ailleurs... Vérifier peut-être le "Count" immédiatement après avoir défini votre requête. Vous utilisez vraiment un "DataSet" ou vous parlez de la liste retournée par la requête.


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    • Marqué comme réponse BerBuz jeudi 16 février 2012 16:55
    • Non marqué comme réponse BerBuz jeudi 16 février 2012 16:55
    •  
  • jeudi 16 février 2012 17:02
     
     Traitée A du code

    Bonjour Partice Scribe,

    Je parle de la liste retournée par la requête, pas d’un  objet  dataset.

    Il est vrai que j’ai enlevé les lignes de leur contexte pour que ça ne prenne pas trop de place.  Et l’exemple que j’ai donné fonctionne dans les 2 cas. Le fait que vos essais aient donnée le bon résultat m’a incité à chercher autours et j’ai trouvé la raison du dysfonctionnement.

    Je l’explique ci-dessous pour ceux que ça intéresse, la vraie séquence était  proche de celle-ci:

     

    Function Logs(RFR As FormCollection) As ActionResult
    
    Dim Tlog = From l In db.MbeLogs Select l
    Dim s As String =  String.Empty
    
    IfNotString.IsNullOrWhiteSpace(RFR("Levels")) Then
         s=RFR("Levels")
         Tlog = Tlog.Where(Function(x) x.Level = s)
    EndIf
    
    IfNotString.IsNullOrWhiteSpace(RFR("Source")) Then
         s=RFR("Source")
         Tlog = Tlog.Where(Function(x) x.Source = s)
    EndIf
    
    Return View(Tlog.ToList)

     

    Cette façun de faire ne marche pas car l’exécution de la  requête est réalisée lors de la transformation .ToList, à ce moment-là la variable S a la dernière valeur qu’elle a reçu.  Cela doit revenir à écrire quelque chose comme  … WHERE x.Level=S  AND  x.Source=s  ou S n'a aucun sens pour Level

    La solution consiste à faire en sorte que les S soient distincts. Soit en créant des variables distinctes pour chaque élément de comparaison  soit en instanciant la variable S  dans le bloc Then comme ci-dessous.

    If Not String.IsNullOrWhiteSpace(RFR("Levels")) Then
         Dim s As String =RFR("Levels") 
         Tlog = Tlog.Where(Function(x) x.Level = s)
    End If

    Curieusement cela marche, vous, vous ne pouvez pas utiliser la variable S à l’extérieur du block Then mais Linq s’en accommode fort bien.

    Merci beaucoup pour votre aide.


    • Modifié BerBuz jeudi 16 février 2012 17:06 mise en page
    • Marqué comme réponse BerBuz jeudi 16 février 2012 17:09
    •  
  • jeudi 16 février 2012 17:46
     
     

    Exact. Le point clé est que l'on ne fait que *définir* une requête. Elle sera exécutée au moment ou l'on commence à énumérer les résultats que retournerait cette requête. Toutefois Function(x) a accès au contexte dans lequel elle a été déclarée et peut donc accéder à s même si s est définie dans un bloc "if"...


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".