Delete entity by pkey??

Posts   
 
    
Posts: 1268
Joined: 10-Mar-2006
# Posted on: 15-Mar-2006 05:59:49   

SelfServicing .net 2.0

How do I delete an entity by the primary key?

I half expected that to be a static method: MyEntity.Delete(int Pkey)

Since it was not, I figured it would be in MyEntityCollection. However, it turns out that DeleteMulti() does not take any parameters???

So, currently I am forced to do this: MyEntity myEntity = new MyEntity(pkeyvalue); myEntity.Delete();

Seems silly, since I am doing a fetch for something I already know the value for. I am sure the solution is simple, I just do not see it...

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 15-Mar-2006 07:35:37   

You may use the following overload og DeleteMulti():

YourEntityCollection.DeleteMulti(IPredicate)

Posts: 1268
Joined: 10-Mar-2006
# Posted on: 15-Mar-2006 15:09:36   

I am new at this, but not that new simple_smile

For some reason this particular collection does not have such an overload!

I checked some other collections and they have the overload. The only difference I can think of might be that EntityCollection is part of a Target Per Entity Hierarchy?

Anyway, the only DeleteMulti call there is takes NO parameters.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 15-Mar-2006 15:31:16   

Would you send a code snippet of how did you try to delete with the DeleteMulti()?

Which EntityFactory did you use for constructing your EntityCollection()?

I think you should follow the same way as Polymorphic fetching.

Posts: 1268
Joined: 10-Mar-2006
# Posted on: 15-Mar-2006 22:34:22   

In my signature, I hid that I am using SelfServicing.

So, I simply do:

MyEntityCollection coll=new MyEntityCollection(); coll.DeleteMulti();

It seems any collection class from a Target Per Entity Hierarchy does NOT have these additional overloads. (Non Hierachy entityCollections all have 3 overloads on this method)

What to do?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39928
Joined: 17-Aug-2003
# Posted on: 15-Mar-2006 23:47:57   

They don't need the overloads, as the base collection has them. DeleteMulti(predicate) deletes directly, DeleteMulti() deletes the entities inside the collection.

What you want is in the manual: Using the generated classes, using the entity classes, "Modifying an entity" -> 'option 2'.

MyEntity foo = new MyEntity(); foo.PkField = pkValue; foo.IsNew = false; foo.Delete();

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1268
Joined: 10-Mar-2006
# Posted on: 16-Mar-2006 05:21:36   

They don't need the overloads, as the base collection has them. DeleteMulti(predicate) deletes directly, DeleteMulti() deletes the entities inside the collection.

Otis, I don't understand. I need to be able to call DeleteMulti(predicate) from an Entity that is part of a Hierachy and I cannot (it does not exist). I can call it for any Entity that is not part of a Hierachy.

What you want is in the manual: Using the generated classes, using the entity classes, "Modifying an entity" -> 'option 2'.

MyEntity foo = new MyEntity(); foo.PkField = pkValue; foo.IsNew = false; foo.Delete();

Believe it or not I have read every line of your help files. The code you provided does not work, because the PkField is readonly - I guess I would have to do the ForcedCurrentValueWrite (which is discouraged)?

Back to the original issue - This all seems crazy - I am having this issue because I do not have the same DeleteMulti() for Hierachial Entities as I do regular entities. Can you explain?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39928
Joined: 17-Aug-2003
# Posted on: 16-Mar-2006 08:39:47   

WayneBrantley wrote:

They don't need the overloads, as the base collection has them. DeleteMulti(predicate) deletes directly, DeleteMulti() deletes the entities inside the collection.

Otis, I don't understand. I need to be able to call DeleteMulti(predicate) from an Entity that is part of a Hierachy and I cannot (it does not exist). I can call it for any Entity that is not part of a Hierachy.

Oh, my mistake! Yes, these don't exist. I'll explain why. Say you have a hierarchy of targetperentity: Employee <- Manager. Say you want to delete all employees who manage a department X, which is an FK in manager.

So first you do: delete from manager where managesdepartmentid = @x

this gives a set of N managers. Then you have to delete only the employee rows which match that N manager rows. But you can't, as these rows are gone. You can't do: delete from employee where employeeid in (select managerid from manager where managesdepartmentid = @x)

As the delete of a hierarchical entity which spans multiple tables takes multiple deletes with a filter in this case, and you have to filter on rows which you had to delete first, this won't work. This was the reason the method wasn't added to the hierarchical code.

If it's not in the manual (it should), please let me know and I'll add it. This is a situation I ran into when I had the code in place and I had to take it out because it doesn't work. Ok, it sometimes works, but only if the filter is on the root entity of the hierarchy, which requires knowledge which fields are mapped onto which tables, IMHO that would leak abstraction info and which isn't good.

What you want is in the manual: Using the generated classes, using the entity classes, "Modifying an entity" -> 'option 2'.

MyEntity foo = new MyEntity(); foo.PkField = pkValue; foo.IsNew = false; foo.Delete();

Believe it or not I have read every line of your help files. The code you provided does not work, because the PkField is readonly - I guess I would have to do the ForcedCurrentValueWrite (which is discouraged)?

Selfservicing has an issue with readonly PK values if they're identity. This is because these fields aren't settable in the db. In that corner-case you need to set the PK with forcedcurrentvaluewrite.

Back to the original issue - This all seems crazy - I am having this issue because I do not have the same DeleteMulti() for Hierachial Entities as I do regular entities. Can you explain?

I hope the explanation above illustrates what the problem is and that there's no workaround for this particular issue. I know it kind of sucks, but there's not a satisfying solution to this.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1268
Joined: 10-Mar-2006
# Posted on: 16-Mar-2006 21:34:20   

Say you have a hierarchy of targetperentity: Employee <- Manager. Say you want to delete all employees who manage a department X, which is an FK in manager.

So first you do: delete from manager where managesdepartmentid = @x

this gives a set of N managers. Then you have to delete only the employee rows which match that N manager rows. But you can't, as these rows are gone. You can't do: delete from employee where employeeid in (select managerid from manager where managesdepartmentid = @x)

As the delete of a hierarchical entity which spans multiple tables takes multiple deletes with a filter in this case, and you have to filter on rows which you had to delete first, this won't work. This was the reason the method wasn't added to the hierarchical code.

Well, if a database support cascading deletes (such as MSSQL) and a cascading delete was defined on your relationship between Employee and Manager (which it probably should be), then it would be fine! You are reading the database, so you know what kind of database and you know if they have a cascading delete relationship and therefore only have to issue the one statement:

delete from employee where employeeid in (select managerid from manager where managesdepartmentid = @x)

That would of course be ideal. For others, what would be wrong with just outputting the sql code to take care of this in one operation?

declare @temp TABLE ( @Pkey int) insert into @temp (Pkey) (select EmployeeFK from Manager where managesdepartmentid=@x) delete from Manager where EmployeeFK in (selet pkey from @temp) delete from Employe where EmployeePkey in (selet pkey from @temp)

and so forth....

Thoughts?

If it's not in the manual (it should), please let me know and I'll add it.

I did not see much in the manual in regards to how to use the targetperentity stuff.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39928
Joined: 17-Aug-2003
# Posted on: 17-Mar-2006 00:10:48   

WayneBrantley wrote:

Say you have a hierarchy of targetperentity: Employee <- Manager. Say you want to delete all employees who manage a department X, which is an FK in manager.

So first you do: delete from manager where managesdepartmentid = @x

this gives a set of N managers. Then you have to delete only the employee rows which match that N manager rows. But you can't, as these rows are gone. You can't do: delete from employee where employeeid in (select managerid from manager where managesdepartmentid = @x)

As the delete of a hierarchical entity which spans multiple tables takes multiple deletes with a filter in this case, and you have to filter on rows which you had to delete first, this won't work. This was the reason the method wasn't added to the hierarchical code.

Well, if a database support cascading deletes (such as MSSQL) and a cascading delete was defined on your relationship between Employee and Manager (which it probably should be), then it would be fine! You are reading the database, so you know what kind of database and you know if they have a cascading delete relationship and therefore only have to issue the one statement:

delete from employee where employeeid in (select managerid from manager where managesdepartmentid = @x)

That would of course be ideal. For others, what would be wrong with just outputting the sql code to take care of this in one operation?

There are too many cornercases and a filter can be pretty complex. A feature either has to work or not at all, it can't work 'so so' or 'only in this this and this situation', that's not usable for a developer.

declare @temp TABLE ( @Pkey int) insert into @temp (Pkey) (select EmployeeFK from Manager where managesdepartmentid=@x) delete from Manager where EmployeeFK in (selet pkey from @temp) delete from Employe where EmployeePkey in (selet pkey from @temp)

and so forth....

Thoughts?

That's a solution, but very hard to implement, because the filter has to be simple. Hibernate 3 uses this scheme, but it doesn't work always.

If it's not in the manual (it should), please let me know and I'll add it.

I did not see much in the manual in regards to how to use the targetperentity stuff.

that's transparent, for the developer an entity is an entity. I was referring to the corner case of deleting entities directly of entities which are in that type of hierarchy, which isn't supported, if that's documented or not. I'll check if it is.

It's not supported now, and won't be supported in the future, as it's not possible to get it working properly, without a lot of exceptions.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1268
Joined: 10-Mar-2006
# Posted on: 17-Mar-2006 01:04:56   

While I dont completely grasp all the reasons where it would not work, you have done good work so far, I will trust you. smile

Having said that, I think what I said before would be possible and would work in every case:

Based on the user having cascade deletes in place, you could optionally generate the deletemulti code. Of course, you are reading the database to determine this, just like you read it to determine what can and cannot be in a hierarchy, etc....

just my thoughts.

You have been getting alot of my thoughts lately, probably should let you rest sunglasses

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39928
Joined: 17-Aug-2003
# Posted on: 17-Mar-2006 08:19:53   

WayneBrantley wrote:

While I dont completely grasp all the reasons where it would not work, you have done good work so far, I will trust you. smile

It's indeed pretty complicated, I didn't foresee all the consequences either until I had to rip the code out because it wouldn't work in general cases. It's then better to simply not proceed with the feature but cut it out, even though it might work in some occasions for some customers.

Having said that, I think what I said before would be possible and would work in every case:

Based on the user having cascade deletes in place, you could optionally generate the deletemulti code. Of course, you are reading the database to determine this, just like you read it to determine what can and cannot be in a hierarchy, etc....

true simple_smile . The sad thing is that cascading deletes can be enabled on the dev box but not on the production box, but even then, cascading deletes not always work either (graphs with multiple paths from A to B for example aren't possible in general with cascading deletes, SqlServer gives up in these situations). I found it wasn't appropriate to rely on cascading deletes in the db to have a framework feature to work. Decisions, decisions... wink

just my thoughts. You have been getting alot of my thoughts lately, probably should let you rest sunglasses

heh simple_smile Well, it proves you're enthousiastic, and that's always a good thing simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1268
Joined: 10-Mar-2006
# Posted on: 17-Mar-2006 16:57:25   

I found it wasn't appropriate to rely on cascading deletes in the db to have a framework feature to work. Decisions, decisions...

The framework has many features that rely on many features of the DB in order to work. I understand you have currently chosen to skip this one. Perhaps you will reconsider someday.

proves you're enthousiastic

39 posts in 7 days, thats nothing! wink

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39928
Joined: 17-Aug-2003
# Posted on: 17-Mar-2006 19:14:28   

WayneBrantley wrote:

I found it wasn't appropriate to rely on cascading deletes in the db to have a framework feature to work. Decisions, decisions...

The framework has many features that rely on many features of the DB in order to work. I understand you have currently chosen to skip this one. Perhaps you will reconsider someday.

We removed the interface of the method to avoid having users write code which then doesn't work because the DBA has to set a switch in the db. It's debatable if that's good design, 'Framework design guidelines' by Abrams says so, but others might disagree, I'm fine with that (there are already enough discussions about 'right/wrong' related to CS).

proves you're enthousiastic

39 posts in 7 days, thats nothing! wink

Well, of the thousands of customers we have, you definitely have the record for # of questions in a short time wink

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1268
Joined: 10-Mar-2006
# Posted on: 18-Mar-2006 00:54:37   

In my own defense, I have posted several solutions and answered others questions too! sunglasses

I am going to use your product, so you will get to know me.

I am also going to be doing some add-ons for myself and will probably release them.

Two things related to add-ons.

1) I see that you can include an LPT template from TDL. However, since the task performer determines what a particular template is performed with - how does that work? If I just do an include and reference a file with a LPT extension does it just 'know' to use the DotNet performer?

2) Can .config files include other .config files? I am thinking that would be a GREAT way for me to extend the existing templates, instead of copying. For example, I want to use one of the scenarios that ship with the product, and run my templates after those run. The easy thing would be do define my .config file and then make one entry in the shipping .config file to include mine. Otherwise, if i did distribute a set of add-ons, I would have to have a complete copy of every performer config.

Later.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39928
Joined: 17-Aug-2003
# Posted on: 18-Mar-2006 09:22:43   

WayneBrantley wrote:

In my own defense, I have posted several solutions and answered others questions too! sunglasses

True simple_smile

Two things related to add-ons.

1) I see that you can include an LPT template from TDL. However, since the task performer determines what a particular template is performed with - how does that work? If I just do an include and reference a file with a LPT extension does it just 'know' to use the DotNet performer?

It's that simple simple_smile (you include an ID, which is bound to a template through the templateset, so the template which includes the other template doesn't change if you want to change templatesets)

2) Can .config files include other .config files? I am thinking that would be a GREAT way for me to extend the existing templates, instead of copying. For example, I want to use one of the scenarios that ship with the product, and run my templates after those run. The easy thing would be do define my .config file and then make one entry in the shipping .config file to include mine. Otherwise, if i did distribute a set of add-ons, I would have to have a complete copy of every performer config. Later.

No they can't. You hit the weak spot of the current system. In v2, this has been redesigned (took me 2 weeks, but it now finally works). In there you'll get language definition xml files, platform definition files, template binding definition files (you can add as much as you like, select precedence) and task definition files (as much as you like). From those, you make presets in an easy editor and select such a preset, based on language, platform, templategroup and that's the queue that will be ran.

This way, if someone writes new templates, for example to generate a GUI, s/he can just ship the .tasks file with the additional tasks, and a .templatebindings file with the templateid bindings and the user can then simply add the tasks to his preset, save it as another preset and use the 3rd party templates.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 1268
Joined: 10-Mar-2006
# Posted on: 18-Mar-2006 23:00:14   

Sounds good.

Thanks for all your replies!