Is there a way to search an EntityCollection?

Posts   
 
    
JohnRLewis avatar
JohnRLewis
User
Posts: 27
Joined: 30-Aug-2004
# Posted on: 01-Sep-2004 18:32:18   

Using the adapter scenario.

I'd like to retrieve the contents of a lookup table once,

DataAccessAdapter adapter = new DataAccessAdapter();
EntityCollection relationshipTypes = new EntityCollection(new RelationshipTypeEntityFactory());
adapter.FetchEntityCollection(relationshipTypes, null);

And then in a long running loop of processing other entity types, I'd like to refer to specific entities within the above entity collection. I can't find in the documentation how to do this. There is a Find method on EntityCollection, but I am not able to make it do anything.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 01-Sep-2004 19:01:00   

The find method is part of the IBindingList implementation, and needs a property descriptor, which is kind of cumbersome to create.

Searching in the entity collection will be linear, so you need to traverse all entities and check for a proper field value. This can be slow after a while. If you want to index fast into an entity collection (or better: set of entities), load the entity collection once, create a hashtable and add the entities one by one to the hashtable with the field value you want to index them on as key. As it is a lookup table, I think it's ok to assume the values are unique.

You can then find back the entity fast by using the field value to search on as the key in the hashtable.

All other methods require sequential searches through all the entities. I first thought of adding hashtables for each field in the entities for searches but this would slow down entity collection retrieval which is often not wanted.

Frans Bouma | Lead developer LLBLGen Pro
Banane avatar
Banane
User
Posts: 67
Joined: 01-Sep-2004
# Posted on: 15-Oct-2004 01:58:28   

I understand your point about adding hash tables for each field in the entities for searches...but....

Can you add just a sequential search on a field...it will be very useful. Usually we don't deal with a lot of entities in the collections. If so, we can use our own hash tables but it will be very appreciated to have just a basic way to search, even if it is slow.

By the way thanks for adding the List Of Work that is great !

here is the code that I have done for searching an entity into a collection



public static EntityBase FindEntityInCollection(EntityCollectionBase col,string fieldName,string key)
{
    EntityBase myItem = null;
    foreach(EntityBase item in col)
    {
        if(item.Fields[fieldName].CurrentValue.ToString() == key)
        {
            myItem = item;
            break;
        }
    }
    return myItem;
}


Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Oct-2004 09:57:50   

I'll add it to the todo. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Alvaro
User
Posts: 52
Joined: 01-Jun-2004
# Posted on: 15-Oct-2004 13:55:50   

I thought I would add my own wish here. Why not have search methods that work on the PK of the entities in the collection?

I coded this, and in several scenarios it proved useful:


public bool GetEntityByPK(IEntity2 entity, 
                                         IEntityCollection2 collection, 
                                         out IEntity2 foundEntity) {
    bool res = false;
    foundEntity = null;

    for (int i = 0; i < collection.Count; i++) {
        if (CompareEntitiesByPK(entity, collection[i])) {
            res = true;
            foundEntity = collection[i];
            break;
        }
    }
    return res;
}

public bool CompareEntitiesByPK(IEntity2 a, IEntity2 b) {
    bool res = true;

    if (a.GetType().Equals(b.GetType())) {
        foreach (IEntityField2 field in a.PrimaryKeyFields) {
            if (!field.CurrentValue.Equals(b.Fields
                                                    [field.Name].CurrentValue)) {
                res = false;
                break;
            }
        }
    }
    else {
        res = false;
    }
    return res;
}

Cheers, álvaro.-

Banane avatar
Banane
User
Posts: 67
Joined: 01-Sep-2004
# Posted on: 15-Oct-2004 15:21:30   

Super tx a lot

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 15-Oct-2004 15:30:44   

COmpare by PK is already build in. CustomerCollection customers = new CustomerCollection(); customers.GetMulti(null);

CustomerEntity toFind = new CustomerEntity(); toFind.CustomerID="CHOPS"; toFind.IsNew = false; int index = customers.IndexOf(toFind);

This uses the .Equals() implementation, which compares PK values.

IsNew is set to false as new entities can't be compared on PK values, due to the fact that identity PK's are always 0, so two new entities with an identity PK would be seen as 'equal'.

There is indeed no linear search on the collections, well, there is, IBindingList.Find() but it requires a property descriptor (which is normally provided by the grid it is bound to).

Thanks for the implementations simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 37
Joined: 21-Oct-2004
# Posted on: 21-Oct-2004 20:45:46   

Is there any way to search an entity collection based on Unique Constraint? If not, I think this could add some real power as well.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 21-Oct-2004 20:58:57   

Currently there is no support for that, however with the planned find functionality, I think it will be covered. Till then, a lineary search by yourself will be sufficient, the search currently build in also performs a linear search (as there are no indexes stored) anyway.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 37
Joined: 21-Oct-2004
# Posted on: 21-Oct-2004 21:02:46   

Great, thanks!