SubSonic .Filter() in memory filter

為{幸葍}努か 提交于 2019-12-14 02:25:45

问题


i'm having some issues getting the .Filter() method to work in subsonic, and i'm constantly getting errors like the one below:

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 making calls like the one below- is this the corrent way to use it? There seems to be no documentation on the use of this method

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

thanks in advance


回答1:


The value you filter against needs to be the Property Name, not the database column name.

You might try this:

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

Or here's a slightly more verbose method that works for me based on custom overrides of the .Filter() method. It seemed to work better (for me at least) by explicitly creating the Where beforehand:

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

Here's the overrides:

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

And SubSonic 2.0 doesn't actually support In/NotIn for the IsMatch function, so here's the customized version that does (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;
    }



回答2:


IF you're using .net 3.5 you could just do this with a lambda function:

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



回答3:


Filter is designed to work on a collection - is "objNavigation" a collection? The problem you're running into is that the criteria for Filter() can't be met with the column name "NavHigherID".




回答4:


I was having same prob, try doing your filter like this :

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


来源:https://stackoverflow.com/questions/1036376/subsonic-filter-in-memory-filter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!