Foreign Key not set for an entity related to primary table entity

Posts   
 
    
clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 20-Jul-2010 23:22:11   

LLBLGen Version: 2.6 Template: adapter

Here are my tables and their relationships: One Application to many CheckList (cascade delete) One CheckListType to many CheckList One ApplicationType to many Application One ApplicationType to many CheckListType

I suppose there is a circular path going on: Application -> CheckList -> CheckListType -> ApplicationType -> Application

Below is the code that fails. The code is a test I wrote that recreates the steps of a scenario that is happening in our real software. It encounters the same error as our real software. This scenario in our real software worked using LLBLGen 1.x but no longer works now that we are using LLBLGen 2.6.


private void button2_Click(object sender, EventArgs e)
{
    DataAccessAdapter adapter = new DataAccessAdapter();

    // get application type
    ApplicationTypeEntity appType = new ApplicationTypeEntity();
    appType.Id = 2; // zoning
    if (adapter.FetchEntity(appType))
    {
        // create application entity
        ApplicationEntity app = new ApplicationEntity();
        app.ApplicationType = appType;
        app.Year = 2010;

        // fill application's checklist
        FillApplicationCheckList(ref app, ref appType, ref adapter);

        // now clear it out.
        app.CheckList.Clear();

        // now refill application's checklist
        FillApplicationCheckList(ref app, ref appType, ref adapter);

        // save
        bool refetchAfterSave = true;
        bool recurse = true;
        adapter.SaveEntity(app, refetchAfterSave, recurse);
    }

    adapter.CloseConnection();
}

void FillApplicationCheckList(ref ApplicationEntity app, ref DataAccessAdapter adapter)
{
    // fill default checklist types collection for the application type
    IRelationPredicateBucket checkListTypeBucket = app.ApplicationType.GetRelationInfoCheckListType();
    checkListTypeBucket.PredicateExpression.Add(CheckListTypeFields.Default == true);
    adapter.FetchEntityCollection(app.ApplicationType.CheckListType, checkListTypeBucket);


    // fill application checklist collection by cycling through the 
    // default CheckListTypes and adding a CheckList for each one.
    foreach (CheckListTypeEntity checkListType in app.ApplicationType.CheckListType)
    {
        CheckListEntity checkListItem = new CheckListEntity();
        checkListItem.CheckListType = checkListType;
        checkListItem.Complete = false;
        app.CheckList.Add(checkListItem);
    }
}

Here is the exception that happens when calling SaveEntity().

An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'ApplicationID', table 'GCSLRMS_Buffalo_DB31.PT.CheckList'; column does not allow nulls. INSERT fails.

I have a feeling the problem has something to do with ApplicationType.CheckListType collection. Because in my second test below, I omit filling ApplicationType.CheckListType and just hardcode some values for CheckList.CheckListType instead. I get no error.


private void button3_Click(object sender, EventArgs e)
{
    DataAccessAdapter adapter = new DataAccessAdapter();

    // create application
    ApplicationEntity app = new ApplicationEntity();
    app.ApplicationTypeId = 2; // Zoning
    app.Year = 2010;

    // fill CheckList collection
    CheckListEntity checkList = new CheckListEntity();
    checkList.CheckListTypeId = 1;
    checkList.Complete = false;
    app.CheckList.Add(checkList);

    // clear CheckList collection
    app.CheckList.Clear();

    // refill CheckList collection
    app.CheckList.Add(checkList);

    // save
    bool refetchAfterSave = true;
    bool recurse = true;
    adapter.SaveEntity(app, refetchAfterSave, recurse);

    adapter.CloseConnection();
}

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 21-Jul-2010 02:56:04   

I have to check closely, but It seems to me that you are making a salad of references here. What I recommend is:

  1. Fetch CheckListType in a separate collection
adapter.FetchEntityCollection(anotherCollectionToTraverse, checkListTypeBucket);
  1. Use Ids, instead of entity references.
foreach (CheckListTypeEntity checkListType in anotherCollectionToTraverse)
    {
        CheckListEntity checkListItem = new CheckListEntity();
        checkListItem.CheckListTypeId = checkListType.CheckListTypeId;
        checkListItem.Complete = false;
        app.CheckList.Add(checkListItem);
    }

Let me know how it worked.

David Elizondo | LLBLGen Support Team
clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 21-Jul-2010 15:56:06   

daelmo wrote:

I have to check closely, but It seems to me that you are making a salad of references here.

I agree. Actually I didn't originally write the code (the person who did no longer works for us) so I don't know the reasons for any of the design decisions. All I know is it worked before my attempt at porting the program from LLBLGen 1.x to 2.6.

Thanks for the suggestions.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 21-Jul-2010 16:18:23   

Also I'm not sure which version(build number) of the runtime libraries are you using, but it's always recommended to use the latest.

clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 21-Jul-2010 17:31:34   

Walaa wrote:

Also I'm not sure which version(build number) of the runtime libraries are you using, but it's always recommended to use the latest.

SD.LLBLGen.Pro.ORMSupportClasses.NET20 Runtime version: v2.0.50727 SD.LLBLGen.Pro.DQE.SqlServer.NET20 Runtime version: v2.0.50727

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 21-Jul-2010 19:25:31   

PLease check http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=7725

for how to obtain the runtime build numbers. Thanks simple_smile (what you posted is the .NET version they're build against)

Frans Bouma | Lead developer LLBLGen Pro
clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 21-Jul-2010 20:03:38   

Otis wrote:

PLease check http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=7725

for how to obtain the runtime build numbers. Thanks simple_smile (what you posted is the .NET version they're build against)

SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll file version is 2.6.9.511

clint
User
Posts: 150
Joined: 15-Nov-2005
# Posted on: 21-Jul-2010 20:13:44   

daelmo wrote:

I have to check closely, but It seems to me that you are making a salad of references here. What I recommend is:

  1. Fetch CheckListType in a separate collection
adapter.FetchEntityCollection(anotherCollectionToTraverse, checkListTypeBucket);

I did that in our real program (not the simplified example I gave) and that took care of the problem. As I studied the code in our real program I noticed that all I needed was a list of CheckListTypes for a given ApplicationType. There really was no reason to fill in the ApplicationType.CheckListType collection since it wasn't being used anywhere else.

So, I worked around the problem. I'm still curious what caused the problem in the first place so I can avoid a similar scenario in the future. But I suppose I should devote my time to working on higher priority items for now.

Thanks again.