2009-06-24 12 views
1

je vais avoir quelques problèmes pour trouver la méthode pour travailler dans subsonique, et que je reçois constamment des erreurs comme celle ci-dessous .Filter():SubSonic .Filter() dans le filtre de la mémoire

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.  

Line 36:      bool remove = false; 
Line 37:      System.Reflection.PropertyInfo pi = o.GetType().GetProperty(w.ColumnName); 
Line 38:      if (pi.CanRead) 
Line 39:      { 
Line 40:       object val = pi.GetValue(o, null); 

i » m faire des appels comme celui ci-dessous- est-ce la façon correcte de l'utiliser? Il semble y avoir aucune documentation sur l'utilisation de cette méthode

  NavCollection objTopLevelCol = objNavigation.Where(Nav.Columns.NavHigherID,Comparison.Equals, 0).Filter(); 

merci à l'avance

Répondre

2

La valeur que vous filtrer par rapport doit être le Nom de propriété, pas le nom de la colonne de base de données.

Vous pouvez essayer ceci:

lCol = objNavigation.Where(Nav.HigherIDColumn.PropertyName,Comparison.Equals, 0).Filter(); 

Ou voici une méthode un peu plus bavard qui fonctionne pour moi basé sur des remplacements personnalisés de la méthode .Filter(). Il semblait mieux fonctionner (pour moi au moins) en créant explicitement le cas où l'avance:

SubSonic.Where w = new SubSonic.Where(); 
    w.ColumnName = Nav.HigherIDColumn.PropertyName; 
    w.Comparison = SubSonic.Comparison.NotIn; 
    w.ParameterValue = new string[] { "validvalue1", "validvalue2" }; 

    lCol = objNavigation.Filter(w, false); 

Voici les remplacements:

/// <summary> 
    /// Filters an existing collection based on the set criteria. This is an in-memory filter. 
    /// All existing wheres are retained. 
    /// </summary> 
    /// <returns>NavCollection</returns> 
    public NavCollection Filter(SubSonic.Where w) 
    { 
     return Filter(w, false); 
    } 

    /// <summary> 
    /// Filters an existing collection based on the set criteria. This is an in-memory filter. 
    /// Existing wheres can be cleared if not needed. 
    /// </summary> 
    /// <returns>NavCollection</returns> 
    public NavCollection Filter(SubSonic.Where w, bool clearWheres) 
    { 
     if (clearWheres) 
     { 
      this.wheres.Clear(); 
     } 
     this.wheres.Add(w); 
     return Filter(); 
    } 

    /// <summary> 
    /// Filters an existing collection based on the set criteria. This is an in-memory filter. 
    /// Thanks to developingchris for this! 
    /// </summary> 
    /// <returns>NavCollection</returns> 
    public NavCollection Filter() 
    { 
     for (int i = this.Count - 1; i > -1; i--) 
     { 
      Nav o = this[i]; 
      foreach (SubSonic.Where w in this.wheres) 
      { 
       bool remove = false; 
       System.Reflection.PropertyInfo pi = o.GetType().GetProperty(w.ColumnName); 
       if (pi != null && pi.CanRead) 
       { 
        object val = pi.GetValue(o, null); 
        if (w.ParameterValue is Array) 
        { 
         Array paramValues = (Array)w.ParameterValue; 
         foreach (object arrayVal in paramValues) 
         { 
          remove = !Utility.IsMatch(w.Comparison, val, arrayVal); 
          if (remove) 
           break; 
         } 
        } 
        else 
        { 
         remove = !Utility.IsMatch(w.Comparison, val, w.ParameterValue); 
        } 
       } 


       if (remove) 
       { 
        this.Remove(o); 
        break; 
       } 
      } 
     } 
     return this; 
    } 

Et SubSonic 2.0 ne supporte pas réellement dans/Notin pour la IsMatch fonction, voici donc la version personnalisée qui fait (en subsonique \ Utility.cs):

public static bool IsMatch(SubSonic.Comparison compare, object objA, object objB) 
    { 
     if (objA.GetType() != objB.GetType()) 
      return false; 

     bool isIntegerVal = (typeof(int) == objA.GetType()); 
     bool isDateTimeVal = (typeof(DateTime) == objA.GetType()); 

     switch (compare) 
     { 
      case SubSonic.Comparison.In: 
      case SubSonic.Comparison.Equals: 
       if (objA.GetType() == typeof(string)) 
        return IsMatch((string)objA, (string)objB); 
       else 
        return objA.Equals(objB); 
      case SubSonic.Comparison.NotIn: 
      case SubSonic.Comparison.NotEquals: 
       return !objA.Equals(objB); 
      case SubSonic.Comparison.Like: 
       return objA.ToString().Contains(objB.ToString()); 
      case SubSonic.Comparison.NotLike: 
       return !objA.ToString().Contains(objB.ToString()); 
      case SubSonic.Comparison.GreaterThan: 
       if (isIntegerVal) 
       { 
        return ((int)objA > (int)objB); 
       } 
       else if (isDateTimeVal) 
       { 
        return ((DateTime)objA > (DateTime)objB); 
       } 
       break; 
      case SubSonic.Comparison.GreaterOrEquals: 
       if (isIntegerVal) 
       { 
        return ((int)objA >= (int)objB); 
       } 
       else if (isDateTimeVal) 
       { 
        return ((DateTime)objA >= (DateTime)objB); 
       } 
       break; 
      case SubSonic.Comparison.LessThan: 
       if (isIntegerVal) 
       { 
        return ((int)objA < (int)objB); 
       } 
       else if (isDateTimeVal) 
       { 
        return ((DateTime)objA < (DateTime)objB); 
       } 
       break; 
      case SubSonic.Comparison.LessOrEquals: 
       if (isIntegerVal) 
       { 
        return ((int)objA <= (int)objB); 
       } 
       else if (isDateTimeVal) 
       { 
        return ((DateTime)objA <= (DateTime)objB); 
       } 
       break; 
     } 
     return false; 
    } 
1

Si vous utilisez .net 3.5, vous pouvez simplement faire cela avec une fonction lambda:

NavCollection objTopLevelCol = 
    objNavigation.Where(nav => nav.NavHigherID == 0); 
+0

Salut Adam, Bien que ce soit très simple l'application clients est en 2.0 – Doug

0

Le filtre est conçu pour fonctionner sur une collection - est-ce que "objNavigation" est une collection? Le problème que vous rencontrez est que les critères de Filter() ne peuvent pas être remplis avec le nom de colonne "NavHigherID".

+0

qui est le problème - objNavigation est une collection "NavCollection" composée de "Nav" Je pensais que peut-être je l'utilisais mal - suis-je correct dans mon utilisation de ".WHERE(). Filtre()" en remplacement de ".WHERE(). CHARGE()" ?? et le filtre va-t-il filtrer la collection ou ajouter des wheres à la collection entière de base et recommencer? merci d'avance – Doug

+0

Oh - oui je pense que vous l'avez frappé. Essayez d'utiliser Where (...). Load() pour charger la liste en premier - puis utilisez Filter(). Cela devrait le faire ... –

+0

Salut à nouveau. Le code suivant ne fonctionne toujours pas avec un NullReferenceException (le dernier est là pour que je puisse le voir dans le débogueur) NavCollection objFullCollection = new NavCollection() Load(). NavCollection objTopLevel = objFullCollection.Where (Nav.Columns.NavHigherID, 0) .Filtre(); NavCollection objFinalCol = objTopLevel; – Doug

0

j'avais même prob, essayez de faire votre filtre comme ceci:

lCol = objNavigation.Where("NavHigherID",Comparison.Equals, 0).Filter(); 
+0

Malheureusement, j'ai toujours exactement le même problème.J'ai testé même en chargeant simplement une collection, puis en la chargeant dans une autre collection avec where() et filter (même en faisant exactement ce qui est indiqué ci-dessus) et le "pi" dans la méthode de filtrage est toujours null. Est-ce que tout le monde est sûr que ce n'est pas un bug? Quelqu'un at-il testé et si oui puis-je avoir un exemple de code d'un peu de code de travail? – Doug