Missing Primary Keys in Insert Statement

Posts   
 
    
Posts: 26
Joined: 29-Sep-2011
# Posted on: 03-Aug-2014 00:30:33   

Currently we use v3.1 and I am working on to upgrade our solution to v4.2. To test the new features I created a new project with just one table and generated code with .NET 4.5, Self-Servicing, Template - SD.TemplateBindings.SharedTemplates, Task - SD.Presets.SelfServicing.TwoClasses.

My tables doesnt have any sequences tied to the PK column. Created entity by passing the pk in constructor and I see llblgen generates the select statement to retreview the data. But when i call save all the pk fields are not added to the insert statement and i get null error from oracle.

Here is the code


            UiBamAuditEntity bamaudit = new UiBamAuditEntity(0, "TEST",20,2014);

            bamaudit.MdfctnDt = DateTime.Now;
            bamaudit.Save();

Oracle error because of missing pk fields in insert statement

{"ORA-01400: cannot insert NULL into (\"UFACTS\".\"UI_BAM_AUDIT\".\"YEAR_NU\")"}

Here is the insert statement

    Query: INSERT INTO "UFACTS"."UI_BAM_AUDIT" ("MDFCTN_DT") VALUES (:p1)
    Parameter: :p1 : Date. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: 8/2/2014 4:10:30 PM.



   at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.2\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\Query\ActionQuery.cs:line 234
   at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.ExecuteActionQuery(IActionQuery queryToExecute, ITransaction containingTransaction) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.2\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\SelfServicingSpecific\DaoBase.cs:line 1490
   at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.AddNew(IEntityFields fields, ITransaction containingTransaction) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.2\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\SelfServicingSpecific\DaoBase.cs:line 167
   at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.InsertEntity() in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.2\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\SelfServicingSpecific\EntityBase.cs:line 1097
   at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.PersistQueue(List`1 queueToPersist, Boolean insertActions, ITransaction transactionToUse) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.2\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\SelfServicingSpecific\DaoBase.cs:line 1939
   at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(IPredicate updateRestriction, Boolean recurse) in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.2\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\SelfServicingSpecific\EntityBase.cs:line 697
   at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save() in c:\Myprojects\VS.NET Projects\LLBLGen Pro v4.2\Frameworks\LLBLGen Pro\RuntimeLibraries\ORMSupportClasses\SelfServicingSpecific\EntityBase.cs:line 582
   at UnitTestProject1.UnitTest1.TestMethod1() in c:\UIA\ShortCycleDev\BusinessEntities\UnitTestProject1\UnitTest1.cs:line 39

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 03-Aug-2014 11:27:09   

And if you set the PK fields directly in the code, not in the ctor? I have to check but I do recall this changed for Selfservicing as it shares more code with adapter now: the values passed in the ctor are used for the fetch query, but if it fails, the pk fields aren't set anymore. This is to avoid phantom inserts.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 26
Joined: 29-Sep-2011
# Posted on: 04-Aug-2014 03:51:34   

If i set the primary keys then it works but this is not the solution for us. Most of the developers in the projects have been coding by passing the pk in constructors for years. It will be major refactor effort for us to find all the places we are setting the primary keys in the constructor.

I understand your comment about phantom inserts but is there a way we can bypass this i.e by a setting in a config. Wihtout this we will not be able to upgrade to the new version. Did it change in v4.2 ? We are currently in v3.1.

This works

        UiBamAuditEntity bamaudit = new UiBamAuditEntity(0, "TEST",20,2014);

        if (bamaudit.IsNew)
        {
            bamaudit.BamAdtSeqNu = 0;
            bamaudit.BamTypeCd = "TEST";
            bamaudit.WkNu = 20;
            bamaudit.YearNu = 2014;
        }

        bamaudit.MdfctnDt = DateTime.Now;
        bamaudit.Save();
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 04-Aug-2014 07:00:46   

It indeed was added time ago to avoid phantom inserts (ref...). The field is set for fetching purpose, but it's not marked as Changed.

IMHO, it's best to refactor in a way that this change is taking into account. However, if you want to workaround it, write this in a CommonEntityBase partial class in your generated code project:

namespace <YourRootNamespace>.EntityClasses
{
    public abstract partial class CommonEntityBase
    {
        protected override void OnFetch()
        {
            foreach (var field in this.Fields.PrimaryKeyFields)
            {
                field.IsChanged = true;
            }
        }
    }
}
David Elizondo | LLBLGen Support Team