Home
Help
Register
Log in

Search

 
   Active Threads  

You are here: Home > LLBLGen Pro > Bugs & Issues> ListChanged is fired too early when FetchEntityCollection with PrefetchPath
 

Pages: 1
Bugs & Issues
ListChanged is fired too early when FetchEntityCollection with PrefetchPath
Page:1/1 

  Print all messages in this thread  
Poster Message
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
133 posts
# Posted on: 08-May-2014 23:12:13.  
It looks to me, that CurrentChanged and CurrentItemChanged (means ListChanged)events of bindingsource connected to entitycollection is fired too early, before related entities are loaded.

In my scenario I need to set form caption using fields from related entity 1:1, this is done in CurrentItemChanged. And because ListChanged if fired before related entity is fetched, I get always String.Empty

As a workaround I can call myBindingSource.ResetCurrentItem()

Code:
Using adapter As New DataAccessAdapter
    adapter.FetchEntityCollection(ecol, Nothing, 0, Nothing, prefetchPath)
End Using
BindingSource.ResetCurrentItem()


I tried another workaround, to load data to tempEC first and then add entities by
ecol.Addrange(tempEC)
This works also fine, but as I want to use Context this is not the way.


I think ListChanged should be fired after related entities are fetched.
  Top
daelmo
Support Team



Location:
Guatemala City
Joined on:
28-Nov-2005 23:35:24
Posted:
8088 posts
# Posted on: 09-May-2014 08:03:17.  
Please tell us more about your workflow. When exactly do you need the info from the related table? and How are you using it? Maybe we can advise you on a better place to put your custom code.

David Elizondo
LLBLGen'ing (articles and code snippets) | linkedin | twitter
 
Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
37645 posts
# Posted on: 09-May-2014 09:42:40.  
also be aware that a collection binds through its defaultview (which actually implements IBindingList) and a view has settings to make it update itself always or on demand, see:
http://www.llblgen.com/documentation/4.1/LLBLGen%20Pro%20RTF/hh_goto.htm#Using%20the%20generated%20code/Adapter/gencode_usingentityview_adapter.htm#viewbehavior
Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
133 posts
# Posted on: 09-May-2014 09:49:19.  
Hi,
I build in Winforms forms for editing master data, means entities.
And I change form caption or groupcontrol caption based on data I get from current entity. If I move to another entity or edit and save current one, then caption is always in sync with current entity.

I hook on bindingsource CurrentItemChanged event, when it is fired, then I reread data into caption.
Everything works fine, except situation when I need to show in caption data from related entity. When the form is opened and data are loaded by
Code:
adapter.FetchEntityCollection(ecol, Nothing, 0, Nothing, prefetchPath)

then CurrentItemChanged is fired 3x times (known fact) but in all three cases related entity is nothing.

It means you fire ListChanged event right after loading entitycollections but before you merge related entities into root EC.

Therefore I have to run BindingSource.ResetCurrentItem() after FetchEntityCollection in order to get fired CurrentItemChanged again. This time it has also merged related entities and caption could read data.

For example say I want to edit Order and I want to see in form caption or form's groupcontrol caption: "CustomerName - OrderNo"

I will fetch Orders into entitycollection with prefetch path to Customers
Right after fetching data the event CurrentItemChanged is fired 3x but in all these there cases Order.Customer is Nothing because Customers are not merget into Orders yet.

Therefore something like Caption=Order.Customer.CustomerName & "-" & Order.OrderNo
will not work right after the data load. Therefore I have to call BindingSource.ResetCurrentItem() after fetching data

I hope it is more clear to you. Simply said I think you should fire ListChanged AFTER you merge entities with related entities. This way I can avoid calling BindingSource.ResetCurrentItem() after initial load.


  Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
37645 posts
# Posted on: 09-May-2014 09:57:23.  
What's the origin of the call chain when CurrentItemChanged is raised? I think it's due to the OnPropertyChanged of the FK field, thus something we can't suppress. Did you look at the behavior settings I pointed at?
Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
133 posts
# Posted on: 09-May-2014 10:43:07.  
1/ Yes I read "View behavior on collection changes", thanks.

2/ I am fine to call BindingSource.ResetCurrentItem() after fetching entities with prefetch path if my question or idea is wrong or difficult to study in depth.
Code:
Using adapter As New DataAccessAdapter
    adapter.FetchEntityCollection(ecol, Nothing, 0, Nothing, prefetchPath)
End Using
BindingSource.ResetCurrentItem()



If you want to check the call chain here it is:
Quote:
    FlexMARS.BL.dll!FlexMARS.BL.ExBusinessObjectBase.ManagedBindingSource_CurrentItemChanged(Object sender, System.EventArgs e) Line 196 + 0x59 bytes    Basic
    System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.OnCurrentChanged(System.EventArgs e) + 0x12d bytes    
    System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.ChangeRecordState(int newPosition, bool validating, bool endCurrentEdit, bool firePositionChange, bool pullData) + 0x175 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.List_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) + 0x230 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.BindingSource.InnerList_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) + 0x45 bytes    
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.EntityViewBase< FlexMARS.DAL.Data.EntityClasses.WorkInstructionRevisionEntity>.OnListChanged(int index, System.ComponentModel.ListChangedType typeOfChange) Line 739    C#
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.EntityViewBase< FlexMARS.DAL.Data.EntityClasses.WorkInstructionRevisionEntity>._relatedCollectionListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) Line 954    C#
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.CollectionCore< FlexMARS.DAL.Data.EntityClasses.WorkInstructionRevisionEntity>.OnListChanged(int index, System.ComponentModel.ListChangedType typeOfChange) Line 925    C#
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.CollectionCore< FlexMARS.DAL.Data.EntityClasses.WorkInstructionRevisionEntity>.SD.LLBLGen.Pro.ORMSupportClasses.IEntityCollectionCoreInternal.CompleteFetchOperation() Line 1517    C#
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase. ExecuteMultiRowRetrievalQuery(SD.LLBLGen.Pro.ORMSupportClasses.IRetrievalQuery queryToExecute, SD.LLBLGen.Pro.ORMSupportClasses.IEntityFactory2 entityFactory, SD.LLBLGen.Pro.ORMSupportClasses.IEntityCollection2 collectionToFill, SD.LLBLGen.Pro.ORMSupportClasses.IFieldPersistenceInfo[] fieldsPersistenceInfo, bool allowDuplicates, SD.LLBLGen.Pro.ORMSupportClasses.IEntityFields2 fieldsUsedForQuery) Line 617    C#
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase. FetchEntityCollectionInternal(SD.LLBLGen.Pro.ORMSupportClasses.QueryParameters parameters) Line 4262    C#
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase. FetchEntityCollection(SD.LLBLGen.Pro.ORMSupportClasses.QueryParameters parameters) Line 2202    C#
    FlexMARS.DAL.dll!FlexMARS.DAL.DataAccessAdapterEx.ProvedFetchEntityCollection( SD.LLBLGen.Pro.ORMSupportClasses.QueryParameters parameters) Line 327 + 0xf bytes    Basic
    FlexMARS.DAL.dll!FlexMARS.DAL.DataAccessAdapterEx.<closure>.<lambda6>() Line 310 + 0x29 bytes    Basic
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.RecoveryStrategyBase. Execute<bool>(System.Func<bool> toExecute) Line 123 + 0x15 bytes    C#
    FlexMARS.DAL.dll!FlexMARS.DAL.DataAccessAdapterEx.FetchEntityCollection( SD.LLBLGen.Pro.ORMSupportClasses.QueryParameters parameters) Line 310 + 0x56 bytes    Basic
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase. FetchEntityCollection(SD.LLBLGen.Pro.ORMSupportClasses.IEntityCollection2 collectionToFill, SD.LLBLGen.Pro.ORMSupportClasses.IRelationPredicateBucket filterBucket, int maxNumberOfItemsToReturn, SD.LLBLGen.Pro.ORMSupportClasses.ISortExpression sortClauses, SD.LLBLGen.Pro.ORMSupportClasses.IPrefetchPath2 prefetchPath, SD.LLBLGen.Pro.ORMSupportClasses.ExcludeIncludeFieldsList excludedIncludedFields, int pageNumber, int pageSize) Line 2174    C#
    SD.LLBLGen.Pro.ORMSupportClasses.dll!SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase. FetchEntityCollection(SD.LLBLGen.Pro.ORMSupportClasses.IEntityCollection2 collectionToFill, SD.LLBLGen.Pro.ORMSupportClasses.IRelationPredicateBucket filterBucket, int maxNumberOfItemsToReturn, SD.LLBLGen.Pro.ORMSupportClasses.ISortExpression sortClauses, SD.LLBLGen.Pro.ORMSupportClasses.IPrefetchPath2 prefetchPath) Line 2070    C#
    FlexMARS.BL.dll!FlexMARS.BL.WorkInstructionRevisionBase.LoadData() Line 139 + 0xa0 bytes    Basic


  Top
Walaa
Support Team



Location:

Joined on:
21-Aug-2005 16:03:48
Posted:
14531 posts
# Posted on: 09-May-2014 13:36:27.  
Which LLBLGen runtime library build no. are you using?
  Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
133 posts
# Posted on: 09-May-2014 14:51:46.  
LLBL Pro v4.1 build 12 March 2014

  Top
daelmo
Support Team



Location:
Guatemala City
Joined on:
28-Nov-2005 23:35:24
Posted:
8088 posts
# Posted on: 13-May-2014 07:44:45.  
Hi Rosacek,

I'm trying to reproduce your scenario. This what I got:
Code:
private void Form1_Load(object sender, EventArgs e)
{
    _orders.EntityFactoryToUse = new OrderEntityFactory();
    _txtOrderId.DataBindings.Add("Text", _ordersBindingSource, "OrderId");
    _txtCompanyName.DataBindings.Add("Text", _ordersBindingSource, "CustomerCompanyName");

    var path = new PrefetchPath2((int)EntityType.OrderEntity);
    path.Add(OrderEntity.PrefetchPathCustomer);
    using (var adapter = new DataAccessAdapter())
    {
        adapter.FetchEntityCollection(_orders, null, path);
    }
}

CustomerCompanyName is a custom property on OrderEntity that simply returns Customer.CompanyName:
Code:
public string CustomerCompanyName
{
    get
    {
        var toReturn = string.Empty;
        if (Customer != null)
        {
            toReturn = Customer.CompanyName;
        }

        return toReturn;
    }
}

_ordersBindingSource binds to the _orders EntityCollection. I have a binding navigator. Everything is working, I mean: _txtCompanyName is showing the Customer.CompanyName, except for the first order, but if I go forward and back to the first one, there it is the name. So I think this is what you are experimenting, sort of, right?
David Elizondo
LLBLGen'ing (articles and code snippets) | linkedin | twitter
 
Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
133 posts
# Posted on: 13-May-2014 09:54:48.  
Yes, seems similar scenario.

I think there are some questions to think of:

1/ Should ListChanged be fired right after entitycollection is filled? Or after also related entities are merged there?

2/ Or should ListChanged be fired after entitycolection is filled and then again after related entities are merged?

3/ Is IList changed when I add related entities? If we think list is just flat table, than NO. But we consider list as a list of any objects, then YES because objects are changed by adding related entities.


  Top
Walaa
Support Team



Location:

Joined on:
21-Aug-2005 16:03:48
Posted:
14531 posts
# Posted on: 14-May-2014 01:02:01.  
Quote:
3/ Is IList changed when I add related entities? If we think list is just flat table, than NO. But we consider list as a list of any objects, then YES because objects are changed by adding related entities.

Should this be valid, no matter how deep is the level of the added or changed entity?

So for a big connected graph, this might cause a lot of events firing everywhere when one entity is added or changed some where.
  Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
133 posts
# Posted on: 14-May-2014 11:41:38.  
Just to have it clear, I was talking about firing ListChanged at the end of collection fetching
Code:
adapter.FetchEntityCollection(ecol, Nothing, 0, Nothing, prefetchPath)


Not about firing ListChanged everytime anything in graph is changed later on.

The initial question was in ListChanged during FetchEntityCollection should be fired immediatelly after entities are added to collection, or defered to the end of FetchEntityCollection processing, when also related entities are merged.


I do the testing if CurrentItemChanged is fired when I change field in related entity. And the result in NO.
It means after changing related entities in graph, we have to fire manualy bindingsource .ResetCurrentItem if we need to reflect such change in databound controls.

Therefore it looks like it is also the answer to my original question:
ListChanged is fired right after fetching entities into collection. This is correct behavior, as changes in related entities never fire ListChanged and we always have to keep in mind to use ResetBindings or ResetCurrentItem if we need to refresh controls databound to related fields/entities.


  Top
Walaa
Support Team



Location:

Joined on:
21-Aug-2005 16:03:48
Posted:
14531 posts
# Posted on: 15-May-2014 01:45:27.  
I was answering the following question:
Quote:
3/ Is IList changed when I add related entities? If we think list is just flat table, than NO. But we consider list as a list of any objects, then YES because objects are changed by adding related entities.
  Top
Pages: 1  


Powered by HnD ©2002-2007 Solutions Design
HnD uses LLBLGen Pro

Version: 2.1.12172008 Final.