LLBLGen 4.1 upgrade - SetEntitySyncInformation

Posts   
 
    
chand
User
Posts: 72
Joined: 05-Aug-2007
# Posted on: 28-Dec-2013 06:54:43   

This method is now throwing errors in this upgrade

at SD.LLBLGen.Pro.ORMSupportClasses.EntityFieldsCore1.get_Item(Int32 index) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Core\EntityFieldsCore.cs:line 1829 at SD.LLBLGen.Pro.ORMSupportClasses.EntityFieldsCore1.SD.LLBLGen.Pro.ORMSupportClasses.IEntityFieldsCore.GetFieldInfo(Int32 index) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Core\EntityFieldsCore.cs:line 1407 at SD.LLBLGen.Pro.ORMSupportClasses.EntityCore1.SyncFKFields(EntitySyncInfo1 syncInfo) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Core\EntityCore.cs:line 1148 at SD.LLBLGen.Pro.ORMSupportClasses.EntityCore1.SetEntitySyncInformation(String fieldName, IEntityCore relatedEntity, IEntityRelation relation) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Core\EntityCore.cs:line 1117 at My.LLBL.EntityClasses.CommonEntityBase.SetEntitySyncInformation(String fieldName, IEntityCore relatedEntity, IEntityRelation relation) in c:\Work\src\My.Services\LLBL\DatabaseGeneric\DbSpecific\CommonEntityBase\CommonEntityBase_Validation.cs:line 278 at SD.LLBLGen.Pro.ORMSupportClasses.EntityCore1.PerformSetupSyncRelatedEntity(IEntityCore relatedEntity, PropertyChangedEventHandler propertiesChangedHandler, String fieldName, IEntityRelation relation, Boolean connectToSaveEvent, Boolean& alreadyFetchedFlag, String[] forfNames) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Core\EntityCore.cs:line 1027 at SD.LLBLGen.Pro.ORMSupportClasses.EntityCore`1.PerformSetupSyncRelatedEntity(IEntityCore relatedEntity, PropertyChangedEventHandler propertiesChangedHandler, String fieldName, IEntityRelation relation, Boolean connectToSaveEvent, String[] forfNames) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.1\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Core\EntityCore.cs:line 996 at My.LLBL.EntityClasses.ClientEntity.SetupSyncMailingAddress(IEntityCore relatedEntity) in c:\Work\src\My.Services\LLBL\DatabaseGeneric\EntityClasses\ClientEntity.cs:line 2036 at My.LLBL.EntityClasses.ClientEntity.SetRelatedEntity(IEntityCore relatedEntity, String fieldName) in c:\Work\src\My.Services\LLBL\DatabaseGeneric\EntityClasses\ClientEntity.cs:line 821 at My.Application.Services.Client.ClientManager.SaveClient(ClientEntity client) in c:\Work\src\My.Services\My.Application.Services\Client\ClientManager_Crud.cs:line 587 at SyncInvokeSaveClient(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 28-Dec-2013 07:06:04   

Please post the exact exception message, the relevant code that triggered that (client/server). Also make sure you are using the latest v4.1 runtime library version. (http://www.llblgen.com/TinyForum/Threads.aspx?ForumID=10)

David Elizondo | LLBLGen Support Team
chand
User
Posts: 72
Joined: 05-Aug-2007
# Posted on: 28-Dec-2013 07:12:04   

That is the exact error stack. You can see the 4.1 paths from LLBL source code in the stack.

Code is failing in the middle of saving a very complex graph.

From the stack can you tell what could have gone wrong?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 28-Dec-2013 07:23:49   

chand wrote:

That is the exact error stack.

Hi chand, I asked you for the exception 'message', as that is only the stack trace but we don't know what is the exception description.

chand wrote:

You can see the 4.1 paths from LLBL source code in the stack.

Yes, but I meant the Runtime Library Version, as there are many builds of the same version. I just want to make sure you are using the latest one. See http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=7717

chand wrote:

Code is failing in the middle of saving a very complex graph.
From the stack can you tell what could have gone wrong?

Is not obvious, but it might be related to some merge you are doing, I don't know. Please try to reduce the code to the minimum lines that still reproduce the problem, because we need to reproduce it over here to understand your issue.

David Elizondo | LLBLGen Support Team
chand
User
Posts: 72
Joined: 05-Aug-2007
# Posted on: 28-Dec-2013 07:30:01   

Sorry about that

"Index was outside the bounds of the array."

Yes using the latest 4.1.

Downloaded today. Release: 13-Dec-2013 Build: November 26th, 2013

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 28-Dec-2013 11:06:24   

Could you limit the graph to a small one (as it relates to client and mailingaddress, the rest isn't relevant) and see whether the problem still occurs? The index error is related to field indexes, as there are no real field objects used anymore, all field data is now stored in a single array. We have not found a situation where indexes can go wrong here but we might have overlooked something, so if you can reproduce it with these two entities alone, please post their characteristics (i.e. whether they have inheritance, or better, a small repro project), so we can try to reproduce it here and look into a fix for the issue.

Frans Bouma | Lead developer LLBLGen Pro
chand
User
Posts: 72
Joined: 05-Aug-2007
# Posted on: 28-Dec-2013 15:07:54   

I will do that and send it your way.

It was frustrating for me as this code was not touched for several years and magically it survived all the prior upgrades and I am trying to understand why in the world it is overriding the undocumented SetEntitySyncInformation method.

Update 1:

Meanwhile in the following code from SyncFKFields

for (int index = 0; index < relation.AmountFields; ++index) { string name1 = relation.GetFKEntityFieldCore(index).Name; -->"MailingAddressId" int fieldIndex1 = this.Fields.GetFieldIndex(name1); --> -1 IFieldInfo fieldInfo = this.Fields.GetFieldInfo(fieldIndex1); --> Index out of range exception

I am wondering in the first line of the 'for loop' seem to contain everything that you need for the rest of the code in that method.

relation.GetFKEntityFieldCore(index);

Also

this.Fields when casted to EntityFields2 seem to reveal all the info you are looking for

However GetFieldIndex method is returning -1.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 29-Dec-2013 12:34:38   

Ok, could you post the code in your override in SetEntitySyncInformation in CommonEntityBase, as that method isn't to be overridden in user code (so the change you made affects the code in the core library). If you comment that out, does the problem go away? (just guessing, I have no idea why your version of the method is overridden, it's not in the templates)

Meanwhile in the following code from SyncFKFields

for (int index = 0; index < relation.AmountFields; ++index)
        {
         string name1 = relation.GetFKEntityFieldCore(index).Name; -->"MailingAddressId"
         int fieldIndex1 = this.Fields.GetFieldIndex(name1); --> -1
         IFieldInfo fieldInfo = this.Fields.GetFieldInfo(fieldIndex1); --> Index out of range exception

I am wondering in the first line of the 'for loop' seem to contain everything that you need for the rest of the code in that method.

Yes, as the relation contains field pairs: fk field - pk field. AmountFields is the # of pk fields and thus the number of field pairs. It looks like the relation used for setting up the sync information is wrong: the fk field isn't part of the entity on which SyncFkFields is called on. SyncFkFields gets the pk side entity passed in.

relation.GetFKEntityFieldCore(index);

Also

this.Fields when casted to EntityFields2 seem to reveal all the info you are looking for

However GetFieldIndex method is returning -1.

Yes, but it creates field objects, and we try to avoid those, as the information needed is inside the fields object, not the individual field objects we had prior to v4.

Frans Bouma | Lead developer LLBLGen Pro
chand
User
Posts: 72
Joined: 05-Aug-2007
# Posted on: 29-Dec-2013 21:14:03   

I think I found the problem.

The code I inherited was unbelievably customized. There are many overrides on the base entities and no one left in the team can tell why it was done so. Through this framework they got a rope that is long enough.. rage

Following is the approximate code.

  1. var client = <incoming client entity instance>

  2. Set certain foreign key id fields as empty fields. (Mailing Address Id is one of them)

a. var emptyFields = entityFactory.CreateFields(); b. var fields = new EntityFields2(client.Fields.ToAray(), null) // this worked fine before 4.1 c. fields[mailaddressfieldindex] = emptyFields[mailingaddressid]

d. client = new ClientEntity(fields);

In this context, in 4.1 the following two calls are not yielding the same result

var fields = new EntityFields2(clients.Fields.ToArray(), null, null); // this calls results in failure in SyncFKFields method

and

var fields = client.Fields; // this works fine in 4.1

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 30-Dec-2013 07:34:24   

I cannot reproduce the problem with your approximate code.

  • Please post the complete code for your overridden SyncFKFields method in CommonEntityBase.
  • Post any relevant information about the Client entity. Is it in inheritance?
David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 30-Dec-2013 10:01:11   

chand wrote:

I think I found the problem.

The code I inherited was unbelievably customized. There are many overrides on the base entities and no one left in the team can tell why it was done so. Through this framework they got a rope that is long enough.. rage

Following is the approximate code.

  1. var client = <incoming client entity instance>

  2. Set certain foreign key id fields as empty fields. (Mailing Address Id is one of them)

a. var emptyFields = entityFactory.CreateFields(); b. var fields = new EntityFields2(client.Fields.ToAray(), null) // this worked fine before 4.1 c. fields[mailaddressfieldindex] = emptyFields[mailingaddressid]

d. client = new ClientEntity(fields);

What's the point of these lines, if I may ask? simple_smile setting the field to null is enough. If the field is not a nullable field (which already is a red flag in that case, why set a field to null if it's not nullable... ) one can always use entity.SetNewFieldValue(index, value), e.g. to set an fk field to null. One can also use entity.NavigatorProperty=null; if the navigator is set:

// if myOrder.Customer is set to a value, this resets myOrder.CustomerID as well.
myOrder.Customer = null;

In this context, in 4.1 the following two calls are not yielding the same result

var fields = new EntityFields2(clients.Fields.ToArray(), null, null); // this calls results in failure in SyncFKFields method

True, as you pass in null for the field indexes. That ctor is public because it is used in the factories, however one should use the factories always, never the constructor directly. For the usage you're using it for, I think there are better alternatives.

Hope this helps

btw, the override of SetEntitySyncInformation is unnecessary and also likely causes some of the problems. I don't know why that method is overriden, but it's also a cause for concern.

Frans Bouma | Lead developer LLBLGen Pro