EntityCollection.SaveMulti in Transaction Fails

Posts   
 
    
Posts: 29
Joined: 05-Sep-2005
# Posted on: 16-Dec-2005 22:20:03   

I have code that I have tested and used in the previous version of LLBL that worked fine. After updating to the newest version (1.0.2005.1) and regenerating my code, it fails. Here is the code:

                 Dim myEntityCollection As New CollectionClasses.BuilderCommunityCollection
                myEntityCollection = _
                        DataShare.DataBase.ShareBuild.DataSupportLayer.BuilderCommunityStruct.ToBuilderCommunityEntityCollection(myCollection)

                'create transactionmanager message
                Dim myName As String = "BuilderCommunity Add"
                Dim transactionManager As New HelperClasses.Transaction(IsolationLevel.ReadCommitted, myName)

                'add new records from collection
                Try
                    'add collection to transactionManager
                    transactionManager.Add(myEntityCollection)
                    'save the individual items
                    myEntityCollection.SaveMulti(True)
                    'commit the transaction
                    transactionManager.Commit()
                    commitSuccessful = True
                Catch ex As Exception
                    'write some type of debug message
                    Debug.Write("Error Adding BuilderCommunity in ShareSynch.  Message: " & ex.Message)
                    'abort and rollback the transaction
                    transactionManager.Rollback()
                    commitSuccessful = False
                Finally
                    'clean up the transaction Manager which will not close database connection
                    transactionManager.Dispose()
                End Try

The key is that I am populating an EntityCollection with new Entities from another SQL table that need added to another SQL table to synchronize the two tables. The table we are writing to in this code uses primary keys, but they are not set as identities. Rather, we write the ID number that is an identity from the old table to this table. I know this seems long-winded but it is relavant to where the code now fails.

The following code is generated from the self servicing two class scenario (either full or full/safe, both the same) for VS 2003 and represents the SaveMulti function for EntityClasses:

        Public Overloads Overrides Function SaveMulti(recurse As Boolean) As Integer
            Dim amountSaved As Integer = 0
            If Not Me.ParticipatesInTransaction Then
                Dim transactionManager As New Transaction(IsolationLevel.ReadCommitted, "SaveMulti")
                transactionManager.Add(Me)
                Try
                    amountSaved = MyBase.SaveMulti(recurse)
                    transactionManager.Commit()
                Catch
                    transactionManager.Rollback()
                    Throw
                End Try
            Else
                amountSaved = MyBase.SaveMulti(recurse)
            End If

            Return amountSaved
        End Function

Since my code is already in a transaction, we skip straight to the Else block (repeated below)

 amountSaved = MyBase.SaveMulti(recurse)

upon executing this line, I get an exception saying the primary record ID is null and cannot be null. That is a correct rule but an incorrect statement. The primary record ID in sql is set to be non-null. However, when I view the EntityCollection items, the primary record ID is NOT null, but contains the correct value.

I cannot figure out why all of the sudden my collection saves fail telling me there is a null value where clearly there is a correct value.

Does anyone have suggestions, or is this really a bug?

Thanks!

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 16-Dec-2005 22:21:42   

By the way, in a debug session I also try typing the following and I get the same primary ID null error message:

EntityCollection.Item(0).Save

Where the item(0) exists and does have a value (non-null) for the primary record id.

Thanks.

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 16-Dec-2005 23:17:13   

I continue to try and find the culprit. I dug into the help file again and it seemed that maybe I should try SaveMulti(False) in that the SaveMulti(True) creates its own transaction, which I have already done.

However, that did not work.

Then I tried just plain SaveMulti() with no input, but it didn't work and I assume that it defaults to a True or False.

I know it worked at one time because I started with a blank database which now has records in it - using the original code.

I'll keep trying while I wait for a suggestion from all you experienced folks. Thanks.

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 16-Dec-2005 23:30:11   

One more thing, I have checked to be sure that my catalog is refreshed and re-generated the code and rebuilt the library.

Same errors even on fresh code.

Hmmmm.

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 16-Dec-2005 23:44:32   

OK, even more testing. I tried removing my transaction and just using the following code:

                 Dim myEntityCollection As New CollectionClasses.ActivityCollection
                myEntityCollection = DataShare.DataBase.ShareBuild.DataSupportLayer.ActivityStruct.ToActivityEntityCollection(myCollection)
                myentitycollection.SaveMulti(True)

Guess what? Same error. Cannot insert Null into primary id because it isn't allowed. However, my collection items did not have a null value for the primary key!!

Hmmm.

I guess I'll try doing each record indvidually and bypass the SaveMulti to troubleshoot more. This is really strange.

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 16-Dec-2005 23:59:49   

Now we are getting to the nitty gritty.

I've tried the following code to isolate to an entity:

                 Dim myEntityCollection As New CollectionClasses.ActivityCollection
                myEntityCollection = DataShare.DataBase.ShareBuild.DataSupportLayer.ActivityStruct.ToActivityEntityCollection(myCollection)
                myEntityCollection.Item(0).Save(True)

And I still get the same error message.

** Question:** What do we think causes the error if the Entity.PrimaryID field has a value in it?

Here is my specific case: I have an EntityClass.ActivityEntity with a field ActivityEntity.ActivityID which is NOT an identity field (there is none in this table) but IS a primary key, int type.

If I view the collection.item(0).ActivityID it has a value (like 6, 7, 76, etc). But, I am still getting this null error in the primary key. Here is the exact error message:

_ "An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'ActivityID', table 'ShareBuild.dbo.Activity'; column does not allow nulls. INSERT fails. The statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception."_

Here is the stack trace:

_ StackTrace: " at SD.LLBLGen.Pro.ORMSupportClasses.ActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.BatchActionQuery.Execute() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.ExecuteActionQuery(IActionQuery queryToExecute, ITransaction containingTransaction) at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.AddNew(IEntityFields fields, ITransaction containingTransaction) at DataShare.DataBase.ShareBuild.DataLayer.EntityClasses.ActivityEntityBase.InsertEntity() in D:\MyVisualStudioProjects\Visual Studio Projects\SQL_Classes\DBShareBuild\DataLayer\EntityBaseClasses\ActivityEntityBase.vb:line 467 at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.CallInsertEntity() at SD.LLBLGen.Pro.ORMSupportClasses.DaoBase.PersistQueue(ArrayList queueToPersist, Boolean insertActions, ITransaction transactionToUse) at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(IPredicate updateRestriction, Boolean recurse) at DataShare.DataBase.ShareBuild.DataLayer.EntityClasses.ActivityEntityBase.Save(IPredicate updateRestriction, Boolean recurse) in D:\MyVisualStudioProjects\Visual Studio Projects\SQL_Classes\DBShareBuild\DataLayer\EntityBaseClasses\ActivityEntityBase.vb:line 188 at SD.LLBLGen.Pro.ORMSupportClasses.EntityBase.Save(Boolean recurse) at DataShare.DataBase.ShareSynch.DataSupportLayer.ActivitySynch.CommitStructure(dsActivityCollection& myCollection, CommitType myType) in D:\MyVisualStudioProjects\Visual Studio Projects\SQL_Classes\DBShareSynch\DataSupportLayer\ActivitySynch.vb:line 421_

Any takers for some suggestions?

David.

Paul.Lewis
User
Posts: 147
Joined: 22-Aug-2005
# Posted on: 17-Dec-2005 05:08:05   

David,

Reading your example it appears you are:

1) Reading a collection - myCollection1 2) Createing a new collection - myCollection2 3) Assigning myCollection1 entities to myCollection2

If this is correct then iterate through the myCollection1 entities setting isNew = true prior to saving.

If this doesn't represent you case, try reading this page (Generated code - Troubleshooting and debugging) in the LLBLGen programmers guide to assist you in debugging.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 17-Dec-2005 12:39:06   

Paul:

Thanks for the reply. I tried your suggestion but to no avail.

I dug deeper into the exception and it appears that the querry being called is

    QueryExecuted   "
    Query: INSERT INTO [dbo].[Activity] ([ActivityNum], [ActivityName], [PhaseID], [Active]) VALUES (@ActivityNum, @ActivityName, @PhaseId, @Active)
    Parameter: @ActivityNum : AnsiStringFixedLength. Length: 5. Precision: 0. Scale: 0. Direction: Input. Value: 10200.
    Parameter: @ActivityName : AnsiStringFixedLength. Length: 30. Precision: 0. Scale: 0. Direction: Input. Value: Framing First Floor         .
    Parameter: @PhaseId : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 1.
    Parameter: @Active : Int32. Length: 0. Precision: 10. Scale: 0. Direction: Input. Value: 1.
"   String

However, the querry needs to insert the ActivityID as well because the ActivityID is the primary key, cannot be zero, but is NOT an identity, so is not dynamically generated. I am passing the ID value in the entity, but the querry doesn't seem to be using it.

Any suggestions as I keep digging?

Thanks.

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 17-Dec-2005 12:47:41   

Paul:

Also, just to be sure, I checked the LLBL project for the ActivityEntity (other entities have this problem, I'm just trying to trouble shoot one first) and the entity is set with the following:

Is PK, true Is readonly, false Is computed, false Is nullable, false Is identity, false

It is also set as index = 0.

So, I assume the settings are correct to allow the field as a PK, but require it's inputting in the INSERT tsql code.

??

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 17-Dec-2005 13:00:55   

Looking through the objects in the ORMSupportClasses, it appears that inserting a new entity passes the fields object with an optional transaction object to the dao class for actual writing to the persistant storage.

I notice as I look at the IEntityFields interface that PrimaryKeyFields collection is a part of the interface.

Thus, I assume for my activity entity, that ActivityID is the item in this PrimaryKeyFields collection. If this is true, does the dao object automatically exclude this field in an insert, even though the Is identity and Is computed are false?

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 18-Dec-2005 02:41:51   

I keep trying to get these records saved, but nothing appears to write the primary key field and I keep getting a "null" exception. Is this a legit bug or have I missed checking something???

David.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 18-Dec-2005 10:23:46   

davidknoble wrote:

I keep trying to get these records saved, but nothing appears to write the primary key field and I keep getting a "null" exception. Is this a legit bug or have I missed checking something???

David.

You set your pk to a value, but at first glance I don't see that code. Could you please check if you actually set the ActivityID to a value? As it's not an identity field, the field has to have a value set by you. Even if it's 0, you have to set it, even if it is already 0 by default.

Right before the save, entity.Fields(CInt(ActivityFIeldIndex.ActivityID)).IsChanged, is that true?

Frans Bouma | Lead developer LLBLGen Pro
Posts: 29
Joined: 05-Sep-2005
# Posted on: 18-Dec-2005 12:24:26   

Otis:

Thanks for replying.

The answer is yes, activityID does have a value. That's what's been perplexing me. However, the IsChanged value is false. The Quote below is from my command window at a breakpoint just before the save:

? myentitycollection.count 9 ? myentitycollection.item(0).activityid 1 ? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).IsChanged False

I'll set a breakpoint as the entity is being created and post some more information at the create time.

Just a moment.

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 18-Dec-2005 12:30:52   

While I'm slowly stepping through the code, here is what's called - 2 routines prior to the CommitStructure() method. First is the base method FirstTimeSynch() which calls a subroutine ConvertStructures(). In all cases, the variables ..._From_ are the existing data and the variables ... To represent the new entities that will be saved to persistant storage.

     Public Overrides Function FirstTimeSynch() As Boolean

        Dim successAdd As Boolean = False
        'clear the collection
        Me._CollectionTo.Clear()
        'clear logs
        Me.ClearLogs()
        'fill collection with all records to add - first time need everything
        Me._CollectionFrom = Me._ObjectFrom.GetAllActivities

        'step through items in collection
        For Each Me._TableFrom In Me._CollectionFrom
            'convert between object structs
            Me.ConvertStructures(Me._TableTo, Me._TableFrom)
            'add to the collection
            Me._CollectionTo.Add(Me._TableTo)
            'write to detail log
            Me.WriteDetailLog(Me._TableTo, CommitType.Add)
        Next

        'commit the transaction
        successAdd = Me.CommitStructure(Me._CollectionTo, CommitType.Add)
        'write to summary log
        Me.WriteSummaryLog(CommitType.Add, Me._CollectionFrom.Count, successAdd)
        Return successAdd

    End Function

And Convert ...

     Public Function ConvertStructures(ByRef myBuild As DataShare.DataBase.ShareBuild.DataSupportLayer.ActivityStruct, _
                                      ByRef myEstimator As DataShare.DataBase.ShareEstimator.DataSupportLayer.ActivityStruct) As Boolean
        'convert the structure between objects
        With myBuild
            .ActivityID = myEstimator.ActivityID
            .ActivityNum = myEstimator.ActivityNum
            .ActivityName = myEstimator.ActivityName
            .PhaseID = myEstimator.PhaseID
            .Active = myEstimator.Active
        End With
        Return True

    End Function

Please excuse the inefficiency of using a structure and converting it to an entity. This was older code when I wasn't sure I could use LLBL Pro as a base and wanted to be able to insert a new data layer without having to reprogram the other layers. Obviously now I'm past that and LLBL is our standard.

I'll analyze what's going on. Just a moment.

David.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 18-Dec-2005 12:31:46   

You may edit your messages, David wink .

(edit)

 'step through items in collection
For Each Me._TableFrom In Me._CollectionFrom
'convert between object structs
Me.ConvertStructures(Me._TableTo, Me._TableFrom)
'add to the collection
Me._CollectionTo.Add(Me._TableTo)
'write to detail log
Me.WriteDetailLog(Me._TableTo, CommitType.Add)
Next

This adds the same entity in every loop iteration, it every time adds _TableTo to CollectionTo. ConvertStructures also doesn't create a new entity. Is that what's supposed to be done? confused

Frans Bouma | Lead developer LLBLGen Pro
Posts: 29
Joined: 05-Sep-2005
# Posted on: 18-Dec-2005 12:51:36   

Ok, here is the command window showing the first entity trying to be saved (currently my code has been changed to only try and save item(0) to get it to work, we are ignoring the other collection items for now).

 ? myentitycollection.item(0)
{DataShare.DataBase.ShareBuild.DataLayer.EntityClasses.ActivityEntity}
    Active: 1
    ActiveContext: Nothing
    ActivityId: 1
    ActivityName: "Framing First Floor           "
    ActivityNum: "10200"
    ConcurrencyPredicateFactoryToUse: Nothing
    CustomProperties: {System.Collections.Hashtable}
    CustomPropertiesOfType: {Length=0}
    EntityFactoryToUse: {DataShare.DataBase.ShareBuild.DataLayer.FactoryClasses.ActivityEntityFactory}
    EntityValidatorToUse: Nothing
    Fields: {SD.LLBLGen.Pro.ORMSupportClasses.EntityFields}
    FieldsCustomProperties: {System.Collections.Hashtable}
    FieldsCustomPropertiesOfType: {Length=5}
    IsDeserializing: False
    IsDirty: True
    IsNew: True
    IsSerializing: False
    LLBLGenProEntityTypeValue: 0
    ObjectID: {System.Guid}
    ParticipatesInTransaction: False
    PhaseId: 1
    PrimaryKeyFields: {Length=1}
    Relations: {DataShare.DataBase.ShareBuild.DataLayer.RelationClasses.ActivityRelations}
    Transaction: Nothing
    Validator: {DataShare.DataBase.ShareBuild.DataLayer.ValidatorClasses.ActivityValidator}

Here is the list for the activityID field:

 ? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).ischanged
False
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).isforeignkey
False
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).isidentity
False
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).isnull
False
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).isnullable
False
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).isprimarykey
True
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).isreadonly
False
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).currentvalue
1 {Integer}
    [Integer]: 1 {Integer}
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).containingobjectname
"ActivityEntity"
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).dbvalue
Nothing
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).expressiontoapply
Nothing
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).identityvaluesequencename
""
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).sourcecatalogname
""
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).sourcecolumndbtype
8
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).sourcecolumnisnullable
False
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).sourcecolumnmaxlength
0
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).sourcecolumnname
"ActivityID"
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).sourceobjectname
"Activity"
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).sourceschemaname
"dbo"
? myentitycollection.item(0).Fields(CInt(ActivityFIeldIndex.ActivityID)).typeconvertertouse
Nothing

As we can see, it is correctly set to a primary key, it is correctly set as NOT an identity, the current value is correctly not NULL but contains an integer value.

If I step throught the next code line:

 myEntityCollection.Item(0).Save(False)

Then I get this exception:

 "An exception was caught during the execution of an action query: Cannot insert the value NULL into column 'ActivityID', table 'ShareBuild.dbo.Activity'; column does not allow nulls. INSERT fails.
The statement has been terminated.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception."

I keep trying by setting the recursive to True and Nothing, but this entity has no sub entities, only a couple of data fields and an integer field that is a primary key to another table (PhaseID) which is simply a non-nullable integer.

Any ideas for further debugging would be GREATLY appreciated. Thanks for your time, Otis.

David.

Posts: 29
Joined: 05-Sep-2005
# Posted on: 18-Dec-2005 13:01:01   

Otis:

Sorry for the lengthy messages, I'll edit out irrelavant items when we're done to conserve space simple_smile

Ok you asked:

This adds the same entity in every loop iteration, it every time adds _TableTo to CollectionTo. ConvertStructures also doesn't create a new entity. Is that what's supposed to be done?

The answer is actually yes, this is ok. However, that is because this is my custom collection of vs structs, not LLBL entities. Soooo., Here is the code in the converstion routine from my struct to your entity collection ... and yes, I only declared the entity outside the for each loop where we add the entity. I modified the code to declare a new entity INSIDE the for each loop and I'll test and EDIT this message !!

    Public Shared Function ToActivityEntityCollection(ByRef myActivityCollection As dsActivityCollection) As CollectionClasses.ActivityCollection

        'define the collection to answer
        Dim myCollection As New CollectionClasses.ActivityCollection

        'define structures to convert
        Dim myStruct As New ActivityStruct
        'Dim myEntity As New EntityClasses.ActivityEntity
        'step through each Activity
        For Each myStruct In myActivityCollection
            Dim myEntity As New EntityClasses.ActivityEntity

            myEntity = ToActivityEntity(myStruct)
            myCollection.Add(myEntity)
        Next

        'return the result
        Return myCollection

    End Function

Ok, that didn't help. Here is the code for the ToActivityEntity() method, where it creates a new entity as well. This is frustrating! I must be missing the forest for the trees although it would be different if this code hadn't worked in the past!

     Public Shared Function ToActivityEntity(ByRef myActivity As ActivityStruct) As EntityClasses.ActivityEntity

        'create structure to hold Activity
        Dim myEntity As New EntityClasses.ActivityEntity

        'check primary key first and fill record if not blank (nothing)
        If Not myActivity.ActivityID = Nothing Then
            myEntity.FetchUsingPK(myActivity.ActivityID)
            If myEntity.ActivityID = 0 Then
                myEntity.ActivityID = myActivity.ActivityID
            End If
        End If
        
        'if no record exists then the Primary Key field returned will be zero
        'be sure to set the Primary Key field to the correct amount
        If myEntity.ActivityID = 0 Then myEntity.ActivityID = myActivity.ActivityID
        
        'now fill the remaining fields.
        If Not myActivity.ActivityNum = Nothing Then
            myEntity.ActivityNum = myActivity.ActivityNum
        End If
        If Not myActivity.ActivityName = Nothing Then
            myEntity.ActivityName = myActivity.ActivityName
        End If
        myEntity.PhaseID= myActivity.PhaseID
        myEntity.Active = myActivity.Active

        'return the filled out structure
        Return myEntity

    End Function

Otis, is there a difference in the way an entity is created between versions when you execute the following code and the activityID does not yet exist in the persistant storage?


Dim myE as New Entity
myE.FetchUsingPK(newActivityID)

myE (entity) now appears to be created and already have the newActivityID value assigned. Based on my code, didn't this used to be a zero return instead of the new value?

Thanks much!!!

Posts: 29
Joined: 05-Sep-2005
# Posted on: 18-Dec-2005 13:32:01   

Otis:

I have found the problem. If I execute the following code, the save performs fine:

                 Dim myEntity As New EntityClasses.ActivityEntity
                myEntity.ActivityID = 100
                myEntity.ActivityName = "TestSave"
                myEntity.ActivityNum = "99999"
                myEntity.PhaseId = 1
                myEntity.Active = 1
                myEntity.Save(True)

However, if I execute the following code, the save throws the Null exception for the ActivityID:

                 Dim myEntity As New EntityClasses.ActivityEntity
                myEntity.FetchUsingPK(100)
                myEntity.ActivityName = "TestSave"
                myEntity.ActivityNum = "99999"
                myEntity.PhaseId = 1
                myEntity.Active = 1
                myEntity.Save(True)

BUT, if you look at the entity prior to the save, the ActivityID field contains the value 100!

Thus, it appears that calling the FetchUsingPK(value), while returning false, sets the value for the Entity, but the save cannot access it.

I can think of some work arounds, like checking for false and setting the entity to New again and then setting the ActivityID again, but that seems redundant and inefficient and I should probably be sure that I am using the entity functions the way you designed them.

Questions for you: In your intended design, is this behavior what you wanted? If so, is there a preferred way to determine if an entity exists in the persistant storage that might not cause this later save problem? I know you are consistently telling users that we have to follow your intended design, which I wholeheartedly agree with simple_smile .

Thanks again, I know you are tremendously busy.

David.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 19-Dec-2005 10:31:44   

davidknoble wrote:

Otis:

I have found the problem. If I execute the following code, the save performs fine:

                 Dim myEntity As New EntityClasses.ActivityEntity
                myEntity.ActivityID = 100
                myEntity.ActivityName = "TestSave"
                myEntity.ActivityNum = "99999"
                myEntity.PhaseId = 1
                myEntity.Active = 1
                myEntity.Save(True)

However, if I execute the following code, the save throws the Null exception for the ActivityID:

                 Dim myEntity As New EntityClasses.ActivityEntity
                myEntity.FetchUsingPK(100)
                myEntity.ActivityName = "TestSave"
                myEntity.ActivityNum = "99999"
                myEntity.PhaseId = 1
                myEntity.Active = 1
                myEntity.Save(True)

BUT, if you look at the entity prior to the save, the ActivityID field contains the value 100!

Thus, it appears that calling the FetchUsingPK(value), while returning false, sets the value for the Entity, but the save cannot access it.

Correct, it doesn't set the PK value. The reason for that is that if you execute a FetchusingPK or simply fetch an entity, it never should become 'dirty'. If the PK is set and becomes dirty, it will. Normally this isn't an issue, only if you re-use the entity fetched.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 29
Joined: 05-Sep-2005
# Posted on: 19-Dec-2005 15:11:30   

Otis:

Makes sense to me! Issue closed!

David.