Complex custom filter criteria class

Complex custom filter criteria class

Old forum URL: forums.lhotka.net/forums/t/9943.aspx


JasminK posted on Sunday, January 16, 2011

Guys, can you help me out? :)

I'm using 3.6 version of CSLA.

I have a ReadOnlyListBase object and I want to implement a filter that will use different stored procedures. And I've created custom criteria class to pass a parameter to an overload DataPortal.Fetch method.

it goes like this:

 

 #region Factory methods


        public static EmployeesiList GetEmployeesList()
        {
            return DataPortal.Fetch<EmployeesList>();
        }

       

        public static EmployeesiList GetEmployeesByDepartment(string department)
        {
            return DataPortal.Fetch<EmployeesList>(new DepartmentCriteria(department));
        }
       
           
       

        private EmployeesList()
        {
           
        }


        #endregion

 


        #region Data Access



        private void DataPortal_Fetch()
        {
            this.IsReadOnly = false;
            RaiseListChangedEvents = false;

            using (var ctx = ContextManager<MyDatabaseDataContext>.GetManager(MyApp.DalLinq.Database.MyDatabase))
            {
                foreach(var data in ctx.DataContext.GetEmployees())
                    this.Add(EmployeeInfo.GetEmployeeInfo(data));
            }


            RaiseListChangedEvents = true;
            this.IsReadOnly = true;
        }

           
        private void DataPortal_Fetch(DepartmentCriteria department)
        {
            this.IsReadOnly = false;
            RaiseListChangedEvents = false;

            using (var ctx = ContextManager<MyDatabaseDataContext>.GetManager(MyApp.DalLinq.Database.MyDatabase))
            {
                foreach(var data in ctx.DataContext.GetEmployeesByDepartment(department.Department))
                {
                    this.Add(EmployeeInfo.GetEmployeeInfo(data));
                }
            }
            this.IsReadOnly = true;
            RaiseListChangedEvents = true;
        }

        #endregion

 

 #region Custom Criteria Classes

        [Serializable]
        private class DepartmentCriteria
        {
            private string _department;
            public string Department
            {
                get { return _department; }
            }
            public DepartmentCriteria(string department)
            {
                _department = department;
            }       
        }
        #endregion

 

I've also added corresponding overloaded Child_Fetch methods to child object.

Anyway, when I try something like:

_employeesList = EmployeesList.GetEmployeesByDepartment("IT department");

i get DataPortal.Fetch failed (DataPortal.Fetch failed (Invalid operation - fetch not allowed))

What am I missing here? :)

 

JonnyBee replied on Monday, January 17, 2011

You must be reaching this code in ReadOnlyListBase.cs:

    protected virtual void DataPortal_Fetch(object criteria)
    {
      throw new NotSupportedException(Resources.FetchNotSupportedException);
    }

 

So your code should loke like this:

        protected override void DataPortal_Fetch(DepartmentCriteria department)
        {
            this.IsReadOnly = false;
            RaiseListChangedEvents = false;

            using (var ctx = ContextManager<MyDatabaseDataContext>.GetManager(MyApp.DalLinq.Database.MyDatabase))
            {
                foreach(var data in ctx.DataContext.GetEmployeesByDepartment(department.Department))
                {
                    this.Add(EmployeeInfo.GetEmployeeInfo(data));
                }
            }
            this.IsReadOnly = true;
            RaiseListChangedEvents = true;
        }

 

 

JasminK replied on Monday, January 17, 2011

No, it's not working. I got an error: 

'MyApp.Library.EmployeesList.DataPortal_Fetch(MyApp.Library.EmployeesList.DepartmentCriteria)': no suitable method found to override'

 

I haven't mentioned that the first overloaded method without parameters (DataPortal.Fetch()) works as it should.

JonnyBee replied on Monday, January 17, 2011

Try this:

        protected override void DataPortal_Fetch(object criteria)
        {

           var department = criteria as DepartmentCriteria;

           if (department == null) throw new InvalidOperationException("No criteria or unknown criteria");

           this.IsReadOnly = false;
            RaiseListChangedEvents = false;

            using (var ctx = ContextManager<MyDatabaseDataContext>.GetManager(MyApp.DalLinq.Database.MyDatabase))
            {
                foreach(var data in ctx.DataContext.GetEmployeesByDepartment(department.Department))
                {
                    this.Add(EmployeeInfo.GetEmployeeInfo(data));
                }
            }
            this.IsReadOnly = true;
            RaiseListChangedEvents = true;
        }

 

 

 

 

JasminK replied on Monday, January 17, 2011

Not working again :)

'Invalid operation - fetch not allowed'

I must admit that this problem really puzzels me. I was 100% sure that the original code I posted here will work, because custom criteria classes are meant to be used that way. It must be some very trivial problem but I'm obviously not smart enough to figure it out :)

stefan replied on Monday, January 17, 2011

Just guessing:

Your EmployeeInfo.GetEmployeeInfo(data) method does call the child Data Portal??? (It should.)

You could even call it directly from within EmployeesList, making the factory method obsolete for this purpose.

 

JasminK replied on Monday, January 17, 2011

Of course, GetEmployeeInfo() calls child fetch method.

I'm still trying to fix this. I'll add another LINQ2SQL class and try from there. Maybe it's something wrong with current LINQ2SQL class because i was experimenting with it a lot :) It's frustrating :)

RockfordLhotka replied on Monday, January 17, 2011

There are some known (and unfixable) issues with passing certain arrays to the child data portal, maybe that's the issue you are encountering? The solution is to pass individual items or lists instead of arrays.

The specific behavior around arrays has changed over the past few versions of CSLA as a few of us put in many hours trying to resolve the issue. Ultimately though, there's at least one scenario where it is impossible to differentiate between an array and a list of parameters when accepting a params parameter (and that's what the child data portal accepts).

JasminK replied on Tuesday, January 18, 2011

I've just investigated and I don't know if problem is with Child_Fetch.

But, EmployeesList.GetAllEmployees() method works fine. I have to mention that I've created multiple overloads for Child_Fetch method that accept results from corresponding methods in LINQ2SQL class (GetAllEmployeesResult, GetEmployeesByDepartmentResult etc...) and when i try _employeesList.GetEmployeesByDepartment("Department with no employees") it returns empty list as it should with no exception thrown. Could this be the indicator that there is a problem with Child_Fetch method?

GetAllEmployeesResult and GetEmployeesByDepartmentResult arrays are very similar. They have the same fields. The only difference is that GetAllEmployeesResult of course contains more records.

Finally, is there some other way I could implement filter on ReadOnlyListBase? :)

RockfordLhotka replied on Tuesday, January 18, 2011

JasminK

Finally, is there some other way I could implement filter on ReadOnlyListBase? :)

There are several ways to implement a filter.

 

JasminK replied on Wednesday, January 19, 2011

Yes, I know about LINQ filter but I just wanted to know about some more techniques. :) This FilterBindingList looks pretty neat.

Thanks a lot Rockford and other guys!

 

P.S still havent fixed that Fetch error but. Guess I'll have to deal with it some time later.

RockfordLhotka replied on Wednesday, January 19, 2011

FilteredBindingList is only useful for Windows Forms. And LINQ queries are not useful for Windows Forms, so you need to pick the right technique based on your UI technology.

JasminK replied on Wednesday, January 19, 2011

It's Windows Forms application and I've already implemented FilteredBindingList. It works as it should.

Thanks again for useful informations :)

Copyright (c) Marimer LLC