UpdateEntitiesDirectly Colum 'X' in field list is ambiguous

Posts   
 
    
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 17-Dec-2012 11:31:42   

I try to update columns of "sale_delivery_detail" table using the following code.

RelationPredicateBucket bucket = new RelationPredicateBucket();
bucket.PredicateExpression.Add(SaleDeliveryDetailFields.FkSaleDeliveryId == saleDeliveryId);
bucket.PredicateExpression.Add(SaleDeliveryDetailFields.FkSaleDeliveryDetailStatusId == (long)SaleDeliveryDetailStatusEnumeration.Editing);
bucket.Relations.Add(SaleDeliveryDetailEntity.Relations.SaleOrderDetailEntityUsingFkSaleOrderDetailId);

SaleDeliveryDetailEntity entityWithNewValues = new SaleDeliveryDetailEntity();

bucket.PredicateExpression.Add(SaleOrderDetailFields.FkSaleOrderDetailTypeId == (long)SaleOrderDetailTypeEnumeration.Item);
entityWithNewValues.FkSaleDeliveryDetailStatusId = (long)SaleDeliveryDetailStatusEnumeration.ToBeProcessed;
UpdateDirectly(entityWithNewValues, bucket);

where UpdateDirectly just set the LastChange and LastChangeUser field and call Adapter.UpdateEntitiesDirectly.

The tables'structure is :

sale_delivery_detail Id FK_sale_delivery_detail_status_Id FK_sale_order_detail_Id LastChange LastChangeUser ...

sale_order_detail Id FK_sale_order_detail_type_Id LastChange LastChangeUser ...

The generated query is this one :

UPDATE ( `sale_order_detail`
INNER JOIN `sale_delivery_detail`  ON  `sale_order_detail`.`Id`=`sale_delivery_detail`.`FK_sale_order_detail_Id`)
SET  `FK_sale_delivery_detail_status_Id`=2, `LastChange`='20121217110410', `LastChangeUser`='DBEJOT\\sylvainb'
WHERE ( ( ( `sale_delivery_detail`.`FK_sale_delivery_Id` = 1 AND `sale_delivery_detail`.`FK_sale_delivery_detail_status_Id` = 1 AND `sale_order_detail`.`FK_sale_order_detail_type_Id` = 1)))

As you can see, the updated columns are not prefixed with the table name so the database throws the following exception "Column 'LastChange' in field list is ambiguous" because LastChange exists in both tables.

Is it a bug or is there something to do to force LLBLGEN to add prefix?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 17-Dec-2012 15:22:38   

looks like MySQL, correct? LLBLGen pro version, runtime library build nr? See: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=7722

Frans Bouma | Lead developer LLBLGen Pro
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 18-Dec-2012 11:50:18   

Yes MySQL

LLBLGEN v3.5 Final (Novembre 6th, 2012)

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 18-Dec-2012 19:28:05   

please check the link Frans (Otis) posted and come back with the exact runtime version (build number).

One other thin, where have LastChange & LastChangeUser being set in code? Are you sure the posted code is the one generating the post SQL?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 19-Dec-2012 06:49:02   

As Walaa said, the generated sql doesn't seems to correspond to the provided code. However I reproduced it using Sakila DB:

Code

public void CatalogInUpdatedColumnsRelationInUpdate()
{
    var filter = new RelationPredicateBucket();
    filter.PredicateExpression.Add(FilmActorFields.FilmId > 1);
    filter.Relations.Add(FilmActorEntity.Relations.ActorEntityUsingActorId);

    var newValues = new FilmActorEntity();
    newValues.LastUpdate = DateTime.Now;

    using (var adapter = new DataAccessAdapter())
    {
        adapter.UpdateEntitiesDirectly(newValues, filter);
    }
}

Generated SQL

UPDATE ( `actor`
         INNER JOIN `film_actor`
             ON `actor`.`actor_id` = `film_actor`.`actor_id`)
SET `last_update` = @p1
WHERE  (((`film_actor`.`film_id` > @p2))) 

Exception

Exception type: Devart.Data.MySql.MySqlException Message: Column 'last_update' in field list is ambiguous

(stack trace attached)

RTL ORMSupportClasses: 3.5.12.1101 MySqlDQE: 3.5.12.0330

We will look into this. In the meantime try to use a workaround: as you are adding the relation because you want to be sure that the connection between rows are satisfied, then you can add a NOT NULL predicate, like:

RelationPredicateBucket bucket = new RelationPredicateBucket();
bucket.PredicateExpression.Add(SaleDeliveryDetailFields.FkSaleDeliveryId == saleDeliveryId);
bucket.PredicateExpression.Add(SaleDeliveryDetailFields.FkSaleDeliveryDetailStatusId == (long)SaleDeliveryDetailStatusEnumeration.Editing);

bucket.PredicateExpression.Add(SaleOrderDetailFields.FkSaleOrderDetailId != DBNull.Value );
...

... or, you can use a FieldCompareSetPredicate.

Attachments
Filename File size Added on Approval
ExceptionDetails.txt 2,781 19-Dec-2012 06:49.16 Approved
David Elizondo | LLBLGen Support Team
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 20-Dec-2012 09:34:11   

daelmo, no I don't think I can use the solution you propose me because I need to filter on SaleOrderDetailFields.FkSaleOrderDetailTypeId

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 20-Dec-2012 14:02:15   

The code indeed won't prefix the fields, as that's in general not necessary. We'll look into how to make this work for you.

(edit) you can instead of using the relationcollection, use a fieldcompareset predicate to formulate a correlated subquery for the where clause. This will then look something like UPDATE foo SET bar=@var WHERE foo.X IN (SELECT X FROM SomeTable WHERE foo.FK=SomeTable.PK)

though it's a little rough to formulate.

At the moment the code for mysql uses simple field name formulations for the update statement, meaning it doesn't include object names. For this particular case, it should however. Problem is is that the code is in the base class, and is used by other databases as well. We'll see what we can change to make it specify full object names in update (join list) SET situations.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 20-Dec-2012 14:54:59   

Ok fixed it.

I added an overload which is currently only used by MySQL (as other DBs use other forms of referring to related tables in updates) for emitting the update set field clauses. You therefore have to use both the ORMSupportclasses dll I attached and the mysql dqe dll to fix the problem.

Test: ('World' test DB for mysql, update 'population' field in city, which is also present in joined country table)

[Test]
public void UpdateCityPopulationDirectly()
{
    var updater = new CityEntity();
    updater.Fields["Population"].ExpressionToApply = (CityFields.Population + 1);
    var bucket = new RelationPredicateBucket(CountryFields.Code=="AFG");
    bucket.Relations.Add(CityEntity.Relations.CountryEntityUsingCountryCode);
    using(var adapter = new DataAccessAdapter())
    {
        Assert.AreEqual(4, adapter.UpdateEntitiesDirectly(updater, bucket));
    }
}

query:

Executed Sql Query: 
    Query: UPDATE ( `country`  INNER JOIN `city`  ON  `country`.`Code`=`city`.`CountryCode`) SET  `city`.`Population`=(`city`.`Population` + @p2) WHERE ( ( ( `country`.`Code` = @p3)))
    Parameter: @p2 : Int32. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: 1.
    Parameter: @p3 : AnsiStringFixedLength. Length: 3. Precision: 0. Scale: 0. Direction: Input. Value: "AFG".
Attachments
Filename File size Added on Approval
MySqlUpdateDirectlyFix.zip 258,692 20-Dec-2012 14:55.09 Approved
Frans Bouma | Lead developer LLBLGen Pro
sybjeb
User
Posts: 81
Joined: 20-Sep-2011
# Posted on: 20-Dec-2012 18:01:04   

It's OK for me. So you'll put these dlls in the next release ?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 20-Dec-2012 18:55:52   

Sure it will be there.