Step-By-Step filtering

Posts   
 
    
softwarea
User
Posts: 57
Joined: 05-Mar-2007
# Posted on: 31-Oct-2008 09:03:00   

Hello guys,

I'm looking for a way to filter an entity collection "step-by-step".

Please have a look at the following code first:


    //STEP 1
    public PvAssistantsCollection GetAllAssistants()
    {
        //Get all assistants stored in the database
        PvAssistantsCollection result = new PvAssistantsCollection();
        result.GetMulti(null);

        return result;
    }

    //STEP 2 uses STEP 1 as input
    public PvAssistantsCollection GetEnabledAssistants()
    {
        //Get all assistants which are enabled
        PvAssistantsCollection result = GetAllAssistants();
        PredicateExpression filterResult = new PredicateExpression();
        filterResult.AddWithAnd(PvAssistantsFields.Ass_Is_Enabled == true);
        result.GetMulti(filterResult);

        return result;
    }

    //STEP 3 uses STEP 2 as input
    public PvAssistantsCollection GetTopLevelAssistants()
    {
        //Get all assistants that have no parent
        PvAssistantsCollection result = GetEnabledAssistants();
        PredicateExpression filterResult = new PredicateExpression();
        filterResult.AddWithAnd(PvAssistantsFields.Ass_Parent_Id == DBNull.Value);
        result.GetMulti(filterResult);

        return result;  <--- those results came out wrong in my testings
    }

As you will see, I try to have separate access to different aggregation levels of my "assistants". Sometimes I want to see all my assistants available, sometimes just the top level assistants and so on. The scenarios are unlimited.

In order to reduce and reuse code, I was hoping I could narrow down the wanted results by a step-by-step approach. However, it doesn't work. The results of "GetTopLevelAssistants()" are often not correct.

It seems as if I can't use an already filtered EntityCollection as the starting point of a new filtering. At least not in the way I'm doing it here.

Could anybody please help me with some good advice?

By the way: This code related posting refers to my former question on the suggested architecture for such an approach: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=14631

Thank you very much, Ingmar

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 31-Oct-2008 10:46:36   

GetMulti() always fetch entities from the database, over and above the newly filtered entities are added to these those already in the collection since you don't clear the collection.

What you are looking for is in-memory filtering of the collection, and this can be done by Entity Views.

softwarea
User
Posts: 57
Joined: 05-Mar-2007
# Posted on: 31-Oct-2008 12:18:34   

Hello Walaa,

aha, I understand.

So I modified my code by using EntityViews and it seems to work like this. However, the code looks unfamiliar to me. Could you please have a short look again and tell me if this is the way to do it?


    //STEP 1
    public EntityView<PvAssistantsEntity> GetAllAssistants()
    {
        //Get all assistants stored in the database
        EntityView<PvAssistantsEntity> result = null;
        try
        {
            PvAssistantsCollection Assistants = new PvAssistantsCollection();
            Assistants.GetMulti(null);
            result = Assistants.DefaultView;
            IPredicate emptyFilter = new PredicateExpression();
            result.Filter = emptyFilter;
        }
        catch (Exception)
        {
        }
        return result; ;
    }
    //STEP 2 uses STEP 1
    public EntityView<PvAssistantsEntity> GetEnabledAssistants()
    {
        //Get all assistants which are enabled
        EntityView<PvAssistantsEntity> result = GetAllAssistants();
        try
        {
            PredicateExpression filterResult = result.Filter as PredicateExpression;
            filterResult.AddWithAnd(PvAssistantsFields.Ass_Is_Enabled == true);
            result.Filter = filterResult;
        }
        catch (Exception)
        {
        }
        return result;
    }
    //STEP 3 uses STEP 2
    public EntityView<PvAssistantsEntity> GetTopLevelAssistants()
    {
        //Get all assistants that have no parent
        EntityView<PvAssistantsEntity> result = GetEnabledAssistants();
        try
        {
            PredicateExpression filterResult = result.Filter as PredicateExpression;
            filterResult.AddWithAnd(PvAssistantsFields.Ass_Parent_Id == DBNull.Value);
            result.Filter = filterResult;
        }
        catch (Exception)
        {
        }
        return result;
    }

And I would have to call one of these methods by


        EntityView<PvAssistantsEntity> Assistants = pvAssistants.GetTopLevelAssistants();

instead of


       PvAssistantsCollection Assistants = pvAssistants.GetTopLevelAssistants();

It works, but is it really best practice? Looks weird to me to suddenly work with EntityViews. Maybe you would just add some kind of wrapper, to go back to EntityCollections in your main application?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 31-Oct-2008 13:38:57   

Use EntityViews for in memory filtering of entityCollections.

Also you can project the results of an EntityView to another EntityCollection. Please check: Projecting data inside an EntityView

So you can Project entityViews back to EntityCollections to return these from your methods and pass them around.

Having said this I think:

1- GetAllAssistants() should use GetMulti to fetch entities from the database, and return an entityCollection.

2- The other methods should either accept an entityCollection as a paramter or retrieve the entityCollection by invoking other methods from within as you did.

3- Then each of these 2 methods, should use an entityView to in-memory filter the specified collection, and project the result into a new entity collection which should be returned from the method.

softwarea
User
Posts: 57
Joined: 05-Mar-2007
# Posted on: 31-Oct-2008 15:04:18   

Perfect!

That's exactly how I refactored my code in the mean time. Thank you so much for your suggestions and your time, Walaa! You helped me a lot.

Ingmar