Extra fields in Entity

Posts   
 
    
Andrius
User
Posts: 68
Joined: 04-Apr-2005
# Posted on: 02-Sep-2005 14:26:38   

Hello

I want to pass for editing in GUI an entity with some Extra fields from related tables. I am using adapter. I've extended a bit entity to include this ExtraField colection of IEntityFields2 I've managed to fetch those Extra fields with one dynamic select together with an entity.

My problem now is to raise an EntityContentsChanged event when those Extra fields in entity are edited in GUI. Could you give me a hint how to achieve this in best way?

bclubb
User
Posts: 934
Joined: 12-Feb-2004
# Posted on: 02-Sep-2005 19:58:53   

Can you post some of your code. It will help give you a better answer to do exactly what you need.

Andrius
User
Posts: 68
Joined: 04-Apr-2005
# Posted on: 05-Sep-2005 10:26:21   

My code for fetching is something like this:


    public abstract class ESGEntityBase : EntityBase2,  ICloneable
    {
    
        private IEntityFields2 extraFields = null;

        public IEntityFields2 ExtraFields
        {
            get { return extraFields; }
            set { extraFields = value; }
        }
................
        }

        public void FetchEntityCollection(IEntityCollection2 collectionToFill, IRelationPredicateBucket bucket, IEntityFields2 extraFields, int maxNumberOfItemsToReturn, ISortExpression sortClauses)
        {
            if (extraFields == null || extraFields.Count == 0)
            {
                this.FetchEntityCollection(collectionToFill, bucket, maxNumberOfItemsToReturn, sortClauses, null);
                return;
            }
            IEntityFactory2 entityFactoryToUse = collectionToFill.EntityFactoryToUse;
            IEntityFields2 entityFields = entityFactoryToUse.CreateFields();

            IEntityFields2 allFields = new EntityFields2(entityFields.Count + extraFields.Count);
            {
                int i = 0;
                for (; i < entityFields.Count; i++)
                {
                    IEntityField2 field = entityFields[i];
                    allFields[i] = field;
                }
                for (int j=0; j < extraFields.Count; j++, i++)
                {
                    IEntityField2 field = extraFields[j];
                    allFields[i] = field;
                }
            }
            DataTable dataTable = new DataTable();
            this.AdapterInternal.FetchTypedList(allFields, dataTable, bucket, maxNumberOfItemsToReturn, sortClauses, true);
            for (int i = 0; i < dataTable.Rows.Count; ++i)
            {
                DataRow dataRow = dataTable.Rows[i];

                ESGEntityBase newEntity = (ESGEntityBase) entityFactoryToUse.Create();
                int columnIndex = 0;
                for (int j = 0; j < newEntity.Fields.Count; ++j, ++columnIndex)
                {
                    object valueInField = dataRow[columnIndex];
                    IEntityField2 fieldDestination = newEntity.Fields[j];
                    SetNewFieldValueFromRow(fieldDestination, valueInField);
                    
                }
                newEntity.Fields.AcceptChanges();

                IEntityFields2 newExtraFields = new EntityFields2(extraFields.Count);
                for (int j = 0; j < extraFields.Count; ++j, ++columnIndex)
                {
                    IEntityField2 extraField = (IEntityField2) ((ICloneable) extraFields[j]).Clone();
                    newExtraFields[j] = extraField;
                    object valueInField = dataRow[columnIndex];
                    SetNewFieldValueFromRow(extraField, valueInField);
                }
                newExtraFields.AcceptChanges();
                newEntity.ExtraFields = newExtraFields;
                collectionToFill.Add(newEntity);
            }
        }

        private void SetNewFieldValueFromRow(IEntityField2 fieldDestination, object valueInField)
        {
            bool isColumnValueDBNull = (valueInField == DBNull.Value);
            fieldDestination.IsNull = isColumnValueDBNull;
            if (isColumnValueDBNull)
            {
                // Store default value for null for type
                fieldDestination.ForcedCurrentValueWrite(this.AdapterInternal.TypeDefaultValueSupplier.DefaultValue(fieldDestination.DataType), null);
            }
            else
            {
                // simply store the value
                fieldDestination.ForcedCurrentValueWrite(valueInField, valueInField);
            }
        }


Since those extra fields are not part of a normal entity, when they are changed in GUI they are not firing EntityContentsChanged event. Maybe I have to register them somewhere?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 05-Sep-2005 18:45:34   

You could look into the Field mapped onto related field feature. When you edit such a field (which is for example order.CompanyName which is mapped onto order.Customer.CompanyName), the changed events are fired.

The ForcedCurrentValueWrite routine doesn't fire the changed event. If you want to fire the changed event, call entity.FlagMeAsChanged();

Frans Bouma | Lead developer LLBLGen Pro
Andrius
User
Posts: 68
Joined: 04-Apr-2005
# Posted on: 06-Sep-2005 08:03:14   

I see, that's what I need. Are those fields fetched together with an entity when using Adapter? Does necessary relation have to exist in RelationPredicateBucket?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 06-Sep-2005 09:10:39   

You've to define a prefetch path to fetch the related entities as well. So in the example of order with the related Customer.CompanyName, you fetch with a prefetch path the Customer entity as well when fetching the Order entity. As they then form a graph, you can simply recursively save the order afterwards.

Frans Bouma | Lead developer LLBLGen Pro
Andrius
User
Posts: 68
Joined: 04-Apr-2005
# Posted on: 06-Sep-2005 13:17:30   

Otis wrote:

You've to define a prefetch path to fetch the related entities as well. So in the example of order with the related Customer.CompanyName, you fetch with a prefetch path the Customer entity as well when fetching the Order entity. As they then form a graph, you can simply recursively save the order afterwards.

As this is prefetchPath I guess it will be separate SELECT statement in DB?

Lets say I am retrieving customer by orderNo so, OrderEntity is already in RelationPredicateBucket relations, and I don't want to perform additional select. Is it possible to retrieve those fields as part of one SELECT if they are already in a bucket ?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 07-Sep-2005 10:27:53   

Andrius wrote:

Otis wrote:

You've to define a prefetch path to fetch the related entities as well. So in the example of order with the related Customer.CompanyName, you fetch with a prefetch path the Customer entity as well when fetching the Order entity. As they then form a graph, you can simply recursively save the order afterwards.

As this is prefetchPath I guess it will be separate SELECT statement in DB?

yes.

Lets say I am retrieving customer by orderNo so, OrderEntity is already in RelationPredicateBucket relations, and I don't want to perform additional select. Is it possible to retrieve those fields as part of one SELECT if they are already in a bucket ?

No. The reason for this is that it might work with this particular setup, but if you have 2 or more join branches in your query (And one left the other right the 3rd inner etc), the resultset will become more complex and duplicates will occur, and the fetch logic can't deal with that. That's not because the fetch logic is retarted but because it's not setup to deal with these resultsets, for the sole reason that duplicates are generally bad for performance. As the code is a general purpose routine, it's not filled with special case parts for every scenario. simple_smile

Frans Bouma | Lead developer LLBLGen Pro