Equals & Contains of entity objects on a collection not working as expected

Posts   
 
    
Rlaan avatar
Rlaan
User
Posts: 14
Joined: 21-Apr-2017
# Posted on: 09-May-2017 11:59:35   

Hello everyone,

Currently I'm having an issue with checking if two entities are the same.

I am using LLBLGen Pro 5.1, Self Servicing with the LLBLGen Runetime Framework.

I have a MSSQL database table with the following values making it unique: LivingroomId (int) EmployeeId (int) Date (date) ShiftTypeEnum (byte)

What am I trying to do, I have ListBoxes, where employees can be selected, and on the Edit I want to change whatever has been changed (new people added, or old people removed).

So I got an original collection of LivingroomShiftEventEntities and a new collection of LivingroomShiftEntities. What I'd like to do is to see the difference and update the database based on that. But when I do a Contains(), Equals or == check it gives false where I expect a true.

(Attachment of watch screenshot is waiting for approval, so for now I just typed it)

Watch output:


originalCollection[0] == shift // output: false
originalCollection[0] // output: {AmstaJanBonga.Business.EntityClasses.LivingroomShiftEventEntity}
shift // output: {AmstaJanBonga.Business.EntityClasses.LivingroomShiftEventEntity}
shift.LivingroomId // output: 2
originalCollection[0].LivingroomId // output: 2
shift.EmployeeId // output: 2
originalCollection[0].EmployeeId // output: 2
shift.Date // output: {9-5-2017 0:00:00 }
originalCollection[0].Date // output: {9-5-2017 0:00:00}
shift.ShiftTypeEnum // output: 0
originalCollection[0].ShiftTypeEnum // output: 0
shift.Equals(originalCollection[0]) // output: false
shift.GetType() // output: {Name = "LivingroomShiftEventEntity" FullName = "..."}
originalCollection[0].GetType() // output: {Name = "LivingroomShiftEventEntity" FullName = "..."}

The code I'm working with (not final code, experimenting to see what's working):

public static void UpdateMulti(LivingroomShiftEventCollection originalCollection, List<LivingroomShiftEventEntity> shifts)
        {
            // The new shift collection, could be identical to the existing originalCollection,
            // but could also be completely different.
            var newCollection = new LivingroomShiftEventCollection();
            newCollection.AddRange(shifts);

            var shiftsToDelete = new LivingroomShiftEventCollection();

            foreach (var shift in originalCollection)
            {
                // The shift doesn't exist in the new collection, thus should be removed.
                if (!newCollection.Contains(shift))
                {
                    shiftsToDelete.Add(shift);
                }
            }

            foreach (var shift in newCollection)
            {
                // There was a new shift added, thus it should be added.
                if (!originalCollection.Contains(shift))
                {
                    shift.Save();
                }
            }

            foreach (var shift in shiftsToDelete)
            {
                shift.Delete();
            }
        }

As you can see, the output is the same, so how come it comes out as false when I do a check? Do I need to override the equals if I wanna do checks based on what makes it unique in the database?

Attachments
Filename File size Added on Approval
equals.PNG 24,688 09-May-2017 11:59.53 Approved
Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 09-May-2017 19:52:54   

It can be much simpler.

Removed employees will be in the RemovedEntitiesTrackerCollection, so you can issue a "delete" against these.

Otherwise you just need to save the collection with the modifications, all new entities will be inserted and modified ones will be updated as well. The framework takes care of this.

Generally speaking, unless you are using a Context to keep unique instances for each entity, you'd better use the PK for comparison, rather than object comparison.

Rlaan avatar
Rlaan
User
Posts: 14
Joined: 21-Apr-2017
# Posted on: 10-May-2017 10:05:45   

Walaa wrote:

It can be much simpler.

Removed employees will be in the RemovedEntitiesTrackerCollection, so you can issue a "delete" against these.

Otherwise you just need to save the collection with the modifications, all new entities will be inserted and modified ones will be updated as well. The framework takes care of this.

Generally speaking, unless you are using a Context to keep unique instances for each entity, you'd better use the PK for comparison, rather than object comparison.

Alright, thank you for the heads up simple_smile But just to verify if I understood and implemented it correctly.

Is this what you meant? It does give me the results I was looking for, but I wanna make sure I do things right simple_smile

public static void UpdateMulti(LivingroomShiftEventCollection originalCollection, LivingroomShiftEventCollection newCollection)
        {
            var tracker = new LivingroomShiftEventCollection();
            originalCollection.RemovedEntitiesTracker = tracker;

            originalCollection.RemovedEntitiesTracker.AddRange(originalCollection);
            originalCollection.AddRange(newCollection);

            originalCollection.RemovedEntitiesTracker.DeleteMulti();
            originalCollection.SaveMulti();
        }

Because it feels incorrect since I am not telling it myself individually what to delete and what to save. Because now it feels like it might delete something that will be added back.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 10-May-2017 11:30:10   

You should add the tracker before you do any actions on the collection (e.g. through a UI). Then when an entity is removed from the collection, it's automatically placed into the tracker, so it's not in the collection anymore. When you then delete the entities in the tracker, they're marked for deletion, so a save action will skip them if they somehow still are in the graph reachable from entities you are saving.

You can automate this with a DataScope btw: it will then automatically add tracker collections to collections and can create a unit of work for you when you're done, See: https://www.llblgen.com/Documentation/5.2/LLBLGen%20Pro%20RTF/Using%20the%20generated%20code/gencode_datascopes.htm

You don't need a tracker to keep track of deleted entities tho: a tracker is just a convenient way to keep track of removed entities from a collection without doing extra work. You can also store them yourself in a list, e.g. by intercepting delete events on the collection.

Frans Bouma | Lead developer LLBLGen Pro
Rlaan avatar
Rlaan
User
Posts: 14
Joined: 21-Apr-2017
# Posted on: 10-May-2017 14:38:54   

Otis wrote:

You should add the tracker before you do any actions on the collection (e.g. through a UI). Then when an entity is removed from the collection, it's automatically placed into the tracker, so it's not in the collection anymore. When you then delete the entities in the tracker, they're marked for deletion, so a save action will skip them if they somehow still are in the graph reachable from entities you are saving.

You can automate this with a DataScope btw: it will then automatically add tracker collections to collections and can create a unit of work for you when you're done, See: https://www.llblgen.com/Documentation/5.2/LLBLGen%20Pro%20RTF/Using%20the%20generated%20code/gencode_datascopes.htm

You don't need a tracker to keep track of deleted entities tho: a tracker is just a convenient way to keep track of removed entities from a collection without doing extra work. You can also store them yourself in a list, e.g. by intercepting delete events on the collection.

Thanks Otis smile