Have a table called person.
which has personid and contactid.
if a person is deleted then i wish to remove the person from the db and also and related contacts for that person.
Is it better practice to do the DELETES in ONE Store procedure or should my business layer first call the pContactDelete and then call pPersonDelete???????
thanks
Niall
Assuming you're using MS SQL Server:
You should probably use ON DELETE CASCADE on your foreign key.
ALTER TABLE Contact
ADD CONSTRAINT FK_PersonContact FOREIGN KEY (PersonId)
REFERENCES Person(PersonId) ON DELETE CASCADE
This will make sure that a contact row is deleted when the person row is deleted. It is a constraint which is always enforced by the database.
You can also set this in SQL Management Studio in the Foreign Key Relationships dialog, INSERT and UPDATE Specification section, Delete Rule -> set to Cascade.
Just make sure that if somewhere you cache your Contact objects in your business layer you refresh your cache as well.
you can define a cascading effect on the your reference key
Any approach you take, data should be in consistent state. It would be simpler if you perform operations on both tables in the same stored procedure. If you put it in your business, I think you should use transaction, so that if your contacts are not deleted, you can rollback deletion of person.
If perchance you're using Oracle you have a couple options.
Set up the foreign key between the PERSON and CONTACT tables to cascade deletes.
Create an ON DELETE trigger and do the deletes there. This option also gives you the opportunity to create any necessary audit trail entries or write to any log files, etc, which might be necessary when something is deleted.
Share and enjoy.
My approach to that problem is to NOT to use cascade delete constraint as a general principle.
Cascading deletes can have bizarre effects when there are cyclic references.
In a production environment, its is advisable to handling the deletion of child references through the one stored procedure.
There is no need to make this call from Business layer as long as you are not performing any significant validation before deleting the contacts
Related
Using Telerik OpenAccess ORM I have 2 objects User and Investment. More specifically Investments contains a foreign key to User as any typical one to many relationship. In other words each User can have mutliple Investments but each Investment can only have one user.
I have then attempted to utilize the open access feature 'Is Managed'
Which should mean that I can do something like User.Investments.Clear(); and it deletes all the related investments (or at least this works fine in many-to-many relationships) but unfortunately when I attempt this I am greeted with the following error.
"Update failed: Telerik.OpenAccess.RT.sql.SQLException: Cannot insert
the value NULL into column 'UserID', table
'CODECorp.dbo.Investment'; column does not allow nulls. UPDATE
fails."
Clearly what the ORM is trying to do is remove the association (i.e. foreign key) from the investment object to the user rather than deleting it. I have confirmed this by running SQL profiler and can see that it's running an Update rather than a Delete.
So what am I missing here? Why is it incorrectly trying to remove the association rather than simply deleting the row as you would expect?
By design, the behaviour of the navigation properties with IsManaged set to True, in scenarios where a child object is deleted from the collection of the parent object, is to remove the relationship between the two objects. In other words, Telerik Data Access (previously known as Telerik OpenAccess ORM) will keep the child record in the database but will generate a statement that attempts to set the foreign key to NULL.
A solution in this situation would be to pass the collection to the Delete method of the context. For example:
dbContext.Delete(User.Investments);
dbContext.SaveChanges();
This will produce the necessary DELETE statement. More details about the management of navigation properties with Telerik Data Access is available in this documentation article.
I hope you find this feasible. I am looking forward to your feedback.
I know that in SQL Server I can use delete on cascade when I delete a parent row in a table, but in some places I read that is better to implement this logic in the application (repository) instead of delete on cascade in SQL Server.
So I have two questions. First, if I don't use on delete cascade in SQL Server, how to solve this situation with Entity Framework.
user A adds the parent register and its children to the context
user B adds a new child to the parent register. So user A does not have this child in the context
user A deletes the parent and all the children that are loaded in his context. These children do not include the new child added by user B.
Well, in practice, there is no problem, when user A tries to delete the parent, there is an exception for referential integrity, and the need to load all its children and try again.
This is an extra work for SQL Server, because it needs to send to the user A all the registers again.
If I use delete on cascade in SQL Server, this problem does not exist, so I think is a good option.
So my second question is, is a good idea to use on delete cascade in SQL Server (or other database) or is better to implement this case in the business logic (repository)?
Thanks.
It's a matter of personal preference - I hear valid arguments for both options.
What is more obvious, more understandable to you?
Do you prefer to have automagic deletion? Then use ON DELETE CASCADE
or do you prefer to be in full control of these situations to know exactly when and what is being deleted? Then implement it in your own custom code
There's no right or wrong, no "better" or "worse" - it's more about your own personal preference and how you feel more comfortable with the code.
Okay. assume I have structure:
School -> students -> StudentParents <- parents -> address
School can have many students, students can be relatives and have the same set of parents (may-to-many). Each parent can have multiple addresses.
Assume that students who have the same set of parents cannot study in different schools.
If given school_Id =5, I want to remove this school and all related records.
How to do this easily in Entity Framework 4?
Answer for your question would be same as this question.
You are trying to solve the problem in the wrong layer. You need to
reconsider your database design specially how you maintain the
referential integrity.
You need to set the "CASCADE DELETE"s of the foreign keys and reflect
that in your Entity Model. Then the database will make the necessary
changes to maintain the referential integrity when you delete that
entity.
Entity framework cannot delete data from database that is not instantiated as object in memory. This means you would need to load school data, all students data, all students parent data and so on, and then you would need to manually delete all the data.
This seems like a lot of work to do, so you may want to take another approach to this problem - delete all this data using stored procedure on database that is mapped to ObjectContext, this would perform better since you would not need to get all the data into memory.
But this also seems troublesome. The best approach would be to create Cascade delete constrain on database and map it also in entity framework's model. This has two advantages - you would need to only load school data and after it is deleted from model, it would be deleted from database and cascade delete would remove all referencing data. But if you have school and students data already in memory, EF will take care of marking those objects from memory as deleted, which will make your data consistent with database state.
The best resolution to this problem depends on whether you may or may not modify database. If you can - go for cascade delete. If you cannot - I would recommend stored procedure approach as better performing (assuming performance is an issue and there is lots of students, parents etc. in database).
I'm building a small db-cleaner app for a QA sql server database. Naturally, I need to delete table rows with dependencies on them.
T-SQL cascading abilities are very limited, so I've tried using NHibernate to simplify matters. But, the only way I found for this was to create a collection for each dependency
in the object-to-delete, and mark that as cascade=delete.
That means creating many, many collections (both in the hbm file and in the C# object) which I don't need for any other purpose. Which makes this method as complicated as just using SQL.
Am I missing something? Is there any easier, more generic way to perform delete-cascade?
Thanks.
EDIT: Just to be clear, I avoid changing the foreign keys in the DB because it's a QA DB, designed to be identical to the production DB.
Eventually I found out a generic way to do the deletion:
This guy wrote a recursive SP which does all the work for you:
http://www.sqlteam.com/article/performing-a-cascade-delete-in-sql-server-7
Needed a little touch-ups (since my DB uses schemas) but works like a charm.
I suppose you have foreign keys defined between related tables in your database ?
You can specify at the foreign key level what should happen with related records when a parent record is being removed.
Check out MSDN for the cascading options, and how to define them:
Cascading FK constraints
Foreign Key Constraints
I've got a pretty large DB hooked up to my Entity Framework. I've got one particular set of tables where a common key (fk) was deleted from the design. When I "update the model from the database", I get a series of errors about this now-missing key.
Why doesn't the update process accurately detect that this key was removed? Also, if I manually remove the property from the model, I just end up with other errors. I also tried to simply delete the table and re-add it, but now the table doesn't show up in the "Add" section of the update wizard.
So, short of deleting the entire thing and starting over, is there any way to recover gracefully? Has the EF team released any newer versions of this wizard that has some of these issues fixed in it already?
Entity Framework does get confused from time to time. What you need to do is delete the Entity Table from the model, then rename the table in SQL Server to TableName_Temp, refresh the model, now the Entity Table should be OK, so delete the entity table again rename it back to the original name and refresh the model once more. This time everything should be fine.
I know this is a messed up procedure but this is the only way I found to fix this issue without blowing away the entire edmx and starting from scratch. Currently at my organization we have a policy not to make changes to the EDMX unless absolutely necessary so that we can delete and recreate when ever needed without any problems.
Hope this helps!