Domanda

Sto riscontrando dei problemi nel far funzionare il metodo .Filter () in subsonico e ricevo costantemente errori come quello qui sotto:

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);

Sto effettuando chiamate come quella qui sotto- è questo il modo corretto di usarlo? Sembra che non ci sia documentazione sull'uso di questo metodo

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

grazie in anticipo

È stato utile?

Soluzione

Il valore filtrato deve essere il Nome proprietà, non il nome della colonna del database.

Potresti provare questo:

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

Oppure ecco un metodo leggermente più dettagliato che funziona per me basato su sostituzioni personalizzate del metodo .Filter (). Sembrava funzionare meglio (almeno per me) creando esplicitamente il Where in anticipo:

    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);

Ecco le sostituzioni:

    /// <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;
    }

E SubSonic 2.0 in realtà non supporta In / NotIn per la funzione IsMatch, quindi ecco la versione personalizzata che funziona (in SubSonic \ 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;
    }

Altri suggerimenti

SE stai usando .net 3.5 puoi semplicemente farlo con una funzione lambda:

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

Il filtro è progettato per funzionare su una raccolta - è " objNavigation " una collezione? Il problema che stai riscontrando è che i criteri per Filter () non possono essere soddisfatti con il nome della colonna "NavHigherID".

Avevo lo stesso problema, prova a fare il filtro in questo modo:

lCol = objNavigation.Where("NavHigherID",Comparison.Equals, 0).Filter();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top