llblgen 2.6 to 3.1 issue

Posts   
 
    
sydneylad
User
Posts: 6
Joined: 12-Aug-2011
# Posted on: 12-Aug-2011 01:47:07   

we deserialise record XML compact 25 into the LLBLGen entity.

like this

Type type = Type.GetType(Assembly.CreateQualifiedName(assemblyName, typeName));
if (null != type)
{
 entity = Activator.CreateInstance(type) as EntityBase2;
 if (null == entity)
 {
  throw new ApplicationException("No entity created by type \"" + type.FullName + "\".");
 }
}


if (null != entity && null != entityXml)
{
   try
   {
     entity.ReadXml(entityXml); 
   }
}

Once we deserialise the records we validate the entity.

we have similar code in many places

ACCOUNTEntity account;
for (int ii = customer.ACCOUNTS.Count - 1; ii >= 0; ii--)
{
  account = customer.ACCOUNTS[ii];
  if (account.CUSTOMER == null)
  {
   // Ensure account has link back to customer.

   customer.ACCOUNTS[ii] = account; 
  }
  Validate(account, null, false);
}

But after I've migrated the llblgen entities from 2.6 to 3.1.

customer.ACCOUNTS[ii] = account; 

is no longer working. its customer entity is always null. this code used to work llblgen 2.6

I Am able to fix it

((IEntity2)account).SetRelatedEntity(customer, "CUSTOMER");

but do u have alternative way of doing than directly calling llblgen internal methods.

Please note we have customized the entityIncludeAdapter.template and entityAdapter.template

we have customized entityIncludeAdapter.template like this ....

<[Foreach RelatedEntity ManyToOne]><[If Not MappedFieldRelationIsHidden]>
        /// <summary> Gets / sets related entity of type '<[RelatedEntityName]>Entity' which has to be set using a fetch action earlier. If no related entity is set for this property, null is returned..<br/><br/><[Foreach CustomProperty MappedFieldNameRelation]>
        /// <[CustomPropertyName]>: <[CustomPropertyValue]><br/><[NextForeach]></summary><[Foreach Attribute MappedFieldNameRelation]>
        <[Attribute]><[NextForeach]>
        public virtual <[RelatedEntityName]>Entity <[MappedFieldNameRelation]>
        {
            get { return _<[CaseCamel MappedFieldNameRelation]>; }
            set
            {
                if(this.IsDeserializing)
                {
                    SetupSync<[MappedFieldNameRelation]>(value);
                    <[If OppositeRelationPresent]>                  
                    if((SerializationHelper.Optimization == SerializationOptimization.Fast) && (value!=null))
                    {
                        ((IEntity2)value).SetRelatedEntity(this, "<[RelatedMappedFieldNameRelation]>");
                    }
                    <[EndIf]>                   
                }
                else
                {
                    SetSingleRelatedEntityNavigator(value, "<[RelatedMappedFieldNameRelation]>", "<[MappedFieldNameRelation]>", _<[CaseCamel MappedFieldNameRelation]>, <[If OppositeRelationPresent]>true<[Else]>false<[EndIf]>); 
                }
            }
        }
<[EndIf]><[NextForeach]><[Foreach RelatedEntity OneToOne]><[If Not MappedFieldRelationIsHidden]>
        /// <summary> Gets / sets related entity of type '<[RelatedEntityName]>Entity' which has to be set using a fetch action earlier. If no related entity is set for this property, null is returned.<br/><br/>
        /// <[Foreach CustomProperty MappedFieldNameRelation]>
        /// <[CustomPropertyName]>: <[CustomPropertyValue]><br/><[NextForeach]></summary><[Foreach Attribute MappedFieldNameRelation]>
        <[Attribute]><[NextForeach]>
        public virtual <[RelatedEntityName]>Entity <[MappedFieldNameRelation]>
        {
            get { return _<[CaseCamel MappedFieldNameRelation]>; }
            set
            {
                if(this.IsDeserializing)
                {
                    SetupSync<[MappedFieldNameRelation]>(value);
<[If OppositeRelationPresent]>                  CallSetRelatedEntityDuringDeserialization(value, "<[RelatedMappedFieldNameRelation]>");
<[EndIf]>               }
                else
                {
                    if(value==null)
                    {
                        DesetupSync<[MappedFieldNameRelation]>(<[If OppositeRelationPresent]>true<[Else]>false<[EndIf]>, true);
                    }
                    else
                    {

<[If OppositeRelationPresent]>                          ((IEntity2)value).SetRelatedEntity(this, "<[RelatedMappedFieldNameRelation]>");
<[EndIf]>                           SetupSync<[MappedFieldNameRelation]>(value);
                    }
                }
            }
        }
<[EndIf]><[NextForeach]>

Please help me.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 12-Aug-2011 10:31:23   

But after I've migrated the llblgen entities from 2.6 to 3.1.

Code: customer.ACCOUNTS[ii] = account;

is no longer working. its customer entity is always null. this code used to work llblgen 2.6

I Am able to fix it Code: ((IEntity2)account).SetRelatedEntity(customer, "CUSTOMER");

Adding an entity to an entity colection through the indexer won't trigger the 2-way relation (PK-FK) synchronization code. You should use the Add() method.

customer.ACCOUNTS.Add(account);

And if this is going to mess the for loop, then collect these accounts you need to add in a temp collection then add them to the specified collection outside the loop.

sydneylad
User
Posts: 6
Joined: 12-Aug-2011
# Posted on: 15-Aug-2011 02:31:37   

Why are we not getting the 2-way relation after deserialise XML into the LLBLGen entity.

Example :

Customer.Account is fine. but account.customer is null. We have similar code is many places. It would be lots of changes for us to deal if we upgrade 2.6 to 3.1.

Please suggest anyway to fix this issue through template if possible.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 15-Aug-2011 10:01:42   

Apparently, I was wrong, using the indexer works.

But after I've migrated the llblgen entities from 2.6 to 3.1.

Code: customer.ACCOUNTS[ii] = account;

is no longer working. its customer entity is always null. this code used to work llblgen 2.6

But also I can't reproduce the above quoted claim using the following code:

var customer = new CustomerEntity("ALFKI");
var prefetch = new PrefetchPath2(EntityType.CustomerEntity);
prefetch.Add(CustomerEntity.PrefetchPathOrders);

using (var adapter = new DataAccessAdapter())
{
    adapter.FetchEntity(customer, prefetch);

    var order = new OrderEntity();
    customer.Orders[0] = order;

    Debug.Assert(order.Customer == customer);
}

Assert passes.

So it might be something in your templates. Could you please describe the changes you have made to the templates, and the reason for these changes.

sydneylad
User
Posts: 6
Joined: 12-Aug-2011
# Posted on: 16-Aug-2011 01:16:39   

I have attached the templates with this. Can you please have look?

Thank you

sydneylad
User
Posts: 6
Joined: 12-Aug-2011
# Posted on: 16-Aug-2011 01:23:15   

2nd template change

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 16-Aug-2011 04:55:44   

(your last file is the same as the 1st one attached) Doing a file diff between the original template and the modified one, I can see there are a lot of changes. Could you please explain what is the purpose of those changes? Especially those where you add/modify/remove code related to Set/Unset related entities, relations, etc. Some things changed in template system in v3.1 so you have to take a look into the template to see if you are putting the right code there.

David Elizondo | LLBLGen Support Team
sydneylad
User
Posts: 6
Joined: 12-Aug-2011
# Posted on: 16-Aug-2011 07:16:46   

We have extended entity to cater for dynamic tables we create in our schema. We have changed few things in template for that. I presume, this issue not related to it.

But I'm more worried at this template change. I tried few things to make it work.

<[Foreach RelatedEntity ManyToOne]><[If Not MappedFieldRelationIsHidden]>
        /// <summary> Gets / sets related entity of type '<[RelatedEntityName]>Entity' which has to be set using a fetch action earlier. If no related entity is set for this property, null is returned..<br/><br/><[Foreach CustomProperty MappedFieldNameRelation]>
        /// <[CustomPropertyName]>: <[CustomPropertyValue]><br/><[NextForeach]></summary><[Foreach Attribute MappedFieldNameRelation]>
        <[Attribute]><[NextForeach]>
        public virtual <[RelatedEntityName]>Entity <[MappedFieldNameRelation]>
        {
            get { return _<[CaseCamel MappedFieldNameRelation]>; }
            set
            {
                if(this.IsDeserializing)
                {
                    SetupSync<[MappedFieldNameRelation]>(value);
                    <[If OppositeRelationPresent]>                  
                    if((SerializationHelper.Optimization == SerializationOptimization.Fast) && (value!=null))
                    {
                        ((IEntity2)value).SetRelatedEntity(this, "<[RelatedMappedFieldNameRelation]>");
                    }
                    <[EndIf]>                   
                }
                else
                {
                    SetSingleRelatedEntityNavigator(value, "<[RelatedMappedFieldNameRelation]>", "<[MappedFieldNameRelation]>", _<[CaseCamel MappedFieldNameRelation]>, <[If OppositeRelationPresent]>true<[Else]>false<[EndIf]>); 
                }
            }
        }
<[EndIf]><[NextForeach]>
Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 16-Aug-2011 08:11:06   

The important question is: Could you reproduce this with the original templates?

If no, then it's definitly something in your modified templates.

sydneylad
User
Posts: 6
Joined: 12-Aug-2011
# Posted on: 17-Aug-2011 06:47:02   

Yes, I am able to reproduce with original templates too.

The following code will work for us, 'Coz it fetch from database.

var customer = new CustomerEntity("ALFKI");
var prefetch = new PrefetchPath2(EntityType.CustomerEntity);
prefetch.Add(CustomerEntity.PrefetchPathOrders);

using (var adapter = new DataAccessAdapter())
{
    adapter.FetchEntity(customer, prefetch);

    var order = new OrderEntity();
    customer.Orders[0] = order;

    Debug.Assert(order.Customer == customer);
}

After I deserialise the entity using compact25 xml, Lets say When I loop through

for (int ii = customer.ACCOUNTS.Count - 1; ii >= 0; ii--)
{
account = customer.ACCOUNTS[ii];
if (account.CUSTOMER == null)
{
// Ensure account has link back to customer.

customer.ACCOUNTS[ii] = account; 
}
Validate(account, null, false);
}

in the above example account.CUSTOMER will be null. In llblgen 2.6 we used to the following to get the 2 way relation.

customer.ACCOUNTS[ii] = account; 

and Customer will be set to the Account entity. but it no longer works for us in 3.1. We have extensively used it across our code. we are not able to get the 2 way relation when we deserialise the entity.

Please let me know if you dont understand my question confused

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 17-Aug-2011 11:18:08   

I must be missing something coz I can't reproduce it with the below code:

var customer = new CustomerEntity("ALFKI");
var prefetch = new PrefetchPath2(EntityType.CustomerEntity);
prefetch.Add(CustomerEntity.PrefetchPathOrders);

using (var adapter = new DataAccessAdapter())
{
    adapter.FetchEntity(customer, prefetch);
}

var writer = new StreamWriter("customer.XML");
string customerXml = String.Empty;
customer.WriteXml(XmlFormatAspect.Compact25, out customerXml);
writer.Write(customerXml);
writer.Close();

StreamReader reader = new StreamReader("customer.XML");
string xmlFromFile = reader.ReadToEnd();
reader.Close();
CustomerEntity customerFromXml = new CustomerEntity();
customerFromXml.ReadXml(xmlFromFile);

Debug.Assert(customerFromXml.Orders[0].Customer == customerFromXml);

Could you please tell me how to reproduce it using the above Northwind based code.