Deletion of enties from an EntityCollection

Posts   
 
    
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 07-Oct-2008 05:53:39   

(Day 4 learning experience) I have a datagrid (Infragistics) with parent child realtionship.

I am using adapter not self service.

This is bound to an entity collection 'entityCollection1' as such in the form load event handler

        PrefetchPath2 CommsPath = new PrefetchPath2((int)EntityType.CasesEntity);
        CommsPath.Add(CasesEntity.PrefetchPathCommunicationsLog);
        adapter.FetchEntityCollection(entityCollection1, null, CommsPath);

After I have made changes (updates and inserts) I use

adapter.SaveEntityCollection(entityCollection1, true, true); to persist the changes back to the database. Works ok! simple_smile

I know one can use adapter.DeleteEntityCollection(entityCollection1) to delete all the records in the entity collection (did not know this until I tried it and got a not nice surprise). I thought it have deleted just the deleted rows.flushed

I see that one needs to capture the deleted rows by capturing these into another entity collection. I have looked at the help but it is not clear or least it does not match what I am trying to achieve.

I have tried add this to my form class

private EntityCollection DeletedData = new EntityCollection();

and modified the form load event handler to

        PrefetchPath2 CommsPath = new PrefetchPath2((int)EntityType.CasesEntity);
        CommsPath.Add(CasesEntity.PrefetchPathCommunicationsLog);
        **entityCollection1.RemovedEntitiesTracker = DeletedData;**         
       adapter.FetchEntityCollection(entityCollection1, null, CommsPath);

In the my save button event handler I call

adapter.SaveEntityCollection(entityCollection1, true, true);

to persist updates and inserts but I am not sure how one handles the deletes. The help talks about unitsofwork and so forth.

All I want to do is delete the rows deleted parents and children or just deleted children back to the database.

How do I use the deleted entity collection to delete the rows deleted in my grid?

Am I on the right track or right off beam? confused

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 07-Oct-2008 06:51:14   

I modified my update logic to

        //adapter.SaveEntityCollection(entityCollection1, true, true);
        UnitOfWork2 uow = new UnitOfWork2();
        uow.AddCollectionForSave(entityCollection1);
        uow.AddCollectionForDelete(entityCollection1);
        uow.Commit(adapter, true);

Needless to say it did not work.

Modified it to

        UnitOfWork2 uow = new UnitOfWork2();
        uow.AddCollectionForSave(entityCollection1,true,true);
        uow.AddCollectionForDelete(DeletedData);
        uow.Commit(adapter, true);

The inserts and updates work but the deletes do not I have used (in the form load event)

        PrefetchPath2 CommsPath = new PrefetchPath2((int)EntityType.CasesEntity);
        CommsPath.Add(CasesEntity.PrefetchPathCommunicationsLog);
        entityCollection1.RemovedEntitiesTracker = DeletedData;
        adapter.FetchEntityCollection(entityCollection1, null, CommsPath);

Where DeletedData was defined as

    private DataAccessAdapter adapter = new DataAccessAdapter();
    private EntityCollection DeletedData = new EntityCollection();

Its obvious that I am doing something stupid but what?flushed rage confused

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Oct-2008 08:46:41   

I think you should set the _RemovedEntitiesTracker _after fetch the collection. Please try this:

...
PrefetchPath2 CommsPath = new PrefetchPath2((int)EntityType.CasesEntity);
CommsPath.Add(CasesEntity.PrefetchPathCommunicationsLog);
adapter.FetchEntityCollection(entityCollection1, null, CommsPath);

EntityCollection DeletedData = new EntityCollection(new CasesEntityFactory());
entityCollection1.RemovedEntitiesTracker = DeletedData;         
...
adapter.DeleteEntityCollection(DeletedData);
David Elizondo | LLBLGen Support Team
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 07-Oct-2008 09:38:13   

After last posting I did some more testing and the deletion appeared to work. If I deleted a parent with no children it worked ok. If I deleted a parent with children it work ok. If I deleted two or more parents with children I got an exception.

If I deleted a child by itself it did not delete.

I tried your suggestion but it did not delete anything.

I moved the RemovedEntitiesTracker back before the fetch the collection and it worked ok again.

From your suggestion I changed

private EntityCollection DeletedData = new EntityCollection();

To

private EntityCollection DeletedData = new EntityCollection(new CasesEntityFactory());

and that seems to work a lot better.

Its working except when I delete a child record under a parent. In this case nothing happens.

How can I get this last bit to work.confused confused Also I delete some rows and save the changes, delete some more in the grid and save it again I get an exception. Hardly surprising I suppose.flushed

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 07-Oct-2008 10:48:12   

Its working except when I delete a child record under a parent. In this case nothing happens.

Delete isn't recursive, and also the RemovedEntitiesTracker of a certain entityCollection only include entities removed from that collection not from its children (related entities).

So if you want to track the entities deleted from the children, you should grab their RemovedEntitiesTracker collection too.

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 09-Oct-2008 02:32:34   

Walaa wrote:

Its working except when I delete a child record under a parent. In this case nothing happens.

Delete isn't recursive, and also the RemovedEntitiesTracker of a certain entityCollection only include entities removed from that collection not from its children (related entities).

So if you want to track the entities deleted from the children, you should grab their RemovedEntitiesTracker collection too.

I thought that it would be something like that. How does one do this? Can you please give me an example?

If I get the RemovedEntitiesTracker for a entities children, I suspect that I should delete these before the parent. Is that correct?

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 09-Oct-2008 03:05:35   

Ok I have had another look

    private DataAccessAdapter adapter = new DataAccessAdapter();
    // Parent
    private EntityCollection DeletedCases = new EntityCollection(new CasesEntityFactory());
    // Children
    private EntityCollection DeletedLogs = new EntityCollection(new CommunicationsLogEntityFactory());

    private void Form1_Load(object sender, EventArgs e)
    {
        PrefetchPath2 CommsPath = new PrefetchPath2((int)EntityType.CasesEntity);
        CommsPath.Add(CasesEntity.PrefetchPathCommunicationsLog);
     entityCollection1.RemovedEntitiesTracker = DeletedCases;           
       adapter.FetchEntityCollection(entityCollection1, null, CommsPath);
    }

With my entitycollection how do I get it to track the deleted children

entityCollection1.RemovedEntitiesTracker = DeletedCases; // takes care of the parent and its children

But what do I do with DeletedLogs ??!! _**How can I include tracking for the children?disappointed **_

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 09-Oct-2008 04:47:10   

I think I need something like

entityCollection1.CommunicationsLog.RemovedEntitiesTracker = DeletedLogs;

but of course that is not correct.

How do I get access to the communicationsLog entity collection within my entityCollection1 to set the RemovedEntitiesTracker property?

Am I on the right track or am I chasing my own tail?confused

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 09-Oct-2008 06:50:06   

Yep. LLBLGen framework doesn't perform cascade deletes. You have to add the children to a collectionOfChildrenToBeDeteled. You can do that at some point of your code.

  • set the RemovedEntitiesTracker for the parents.
  • Before you remove an entity from the original collection. Call a method (your own method) that adds the child to another collectionOfChildrenToBeDeleted.
  • Remove the entity from the original collection. That will add the entity to the RemoveTrakerCollection.
  • Save the originalCollection, and perform deltes for the other two collection(RemoveTrackerColleciton and collecitonOfChildrenToBeDeleted). Do this inside a transaction.
David Elizondo | LLBLGen Support Team
he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 09-Oct-2008 09:15:32   

Thats a bit disappointing. rage I would think that hierarchical grids are not that uncommon. You seem to recommend the Janus GridEx which is hierarchical so I am a little disappointed that this is not supported. Maybe an enhancement for the next version - a recursive delete.

Ok my solution knowing the state of play. In my case only capture entities that have a parent (parents will be tracked and cascade deletes will take care of children).

As I am using only one level I don't need to get any children's children. I would if the above entity was itself a parent.

I have to use the before delete event handler to capture this.

private void ultraGrid1_BeforeRowsDeleted(object sender, BeforeRowsDeletedEventArgs e) { e.DisplayPromptMsg = false;

        // Display our own custom message box.
        System.Windows.Forms.DialogResult result =
            System.Windows.Forms.MessageBox.Show(
            "Deleting " + e.Rows.Length.ToString() + " row(s). Continue ?",
            "Delete rows?",
            System.Windows.Forms.MessageBoxButtons.YesNo,
            System.Windows.Forms.MessageBoxIcon.Question);

        // If the user clicked No on the message box, cancel the deletion of rows.
        if (System.Windows.Forms.DialogResult.No == result)
        {
            e.Cancel = true;
            return;
        }

        foreach (UltraGridRow row in e.Rows)
        {
            //MessageBox.Show("Deleted " + row.Cells.Count.ToString());
            if (row.HasParent())
            {
                //MessageBox.Show("Deleting " + row.Cells[0].Value.ToString());
                DataAccessAdapter adapter = new DataAccessAdapter(false);
                CommunicationsLogEntity LogRow = new CommunicationsLogEntity((int)row.Cells[0].Value);
                adapter.FetchEntity(LogRow);
                DeletedLogs.Add(LogRow);
            }
        }

    }

I hope that the above is not too heavy on resources. Still deletes tend to be less common than inserts and updates.

then when I save the updates

private void ultraButton1_Click(object sender, EventArgs e) { //adapter.SaveEntityCollection(entityCollection1, true, true); //MessageBox.Show(DeletedCases.LongCount().ToString()); UnitOfWork2 uow = new UnitOfWork2(); uow.AddCollectionForSave(entityCollection1,true,true); if(DeletedLogs.LongCount() > 0) uow.AddCollectionForDelete(DeletedLogs); if (DeletedCases.LongCount() > 0) uow.AddCollectionForDelete(DeletedCases); uow.Commit(adapter, true); }

I have not worried about transactions at this stage unless the unitofwork2 encapsulates this (I have not checked). I just wanted the crud to work.

I have tested this and it seems to work ok.

Does this seem reasonable? Is there a better way? stuck_out_tongue_winking_eye

he00273
User
Posts: 133
Joined: 02-Oct-2008
# Posted on: 09-Oct-2008 09:25:28   

I think that delete triggers would work much better than cacading deletes. If I have to manage the deletion of children which in turn may have children etc etc, then triggers would be much better and simplify things.

Would you agree or not?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 09-Oct-2008 11:23:46   

Triggers or setting Cascade Delete on the database relations.