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).
Related
I receive a large JSON having different recordsets in the form of arrays in a Xamarin-Forms application. The recordsets are linked with each other through reference Ids. Basically the data is coming from a relational database and I have to map the data into the device's local SQLite. I am using EFCore for that. I am able to successfully set up the Models and their FKs using OnModelCreating override. I have verified it by logging the table creation scripts. Now the issue is, when I AddRange a list of some records, EF Core automatically deletes some of the records. I don't know why and how.
Here is the screenshot in debugging:
The data is a huge graph of different relational records. Earlier I was trying to Add the whole graph by saving only the grandparent record. But there are several children who reference the same record more than once. For example, a UserType is referenced by many users. So EF throws Identity tracking issues. Then I decided to not save using the graph, instead save table by table. And now I am facing this issue. To be specific, there is a total of 11 tables involved in my saving. I am able to save 5 tables that have independent data e.g. UserTypes, EntityTypes, ContactTypes, etc. When I came to the 6th table which references some records of 5 saved tables, I am getting this issue.
Update:
I solved the problem. The issue was in a relationship that was wrongly defined. A WorkOrder can have one Customer only, but a Customer can be linked to many WorkOrders. I was taking it as One-to-One but was ignoring the other way. I updated the one-to-one to one-to-many in Customer entity and everything started working great!
By the way, this we can say the beauty and perfection of EF Core that it can never allow you to persist data against the rules you have defined. Though automatic deleting was a little confusing but ultimately that was my mistake.
I'm using ASP.NET WebApi 2 and loading in part of a relational database structure into the front end website. This allows the user to make changes to multiple tables in a single store and to also view some extra data.
This mostly works pretty well. It means I can store changes to, say a person table and their related clothes and hair color on one call as follows:
db.person.Add(person);
db.SaveChanges();
The problem is that, I don't want to load all the related data. So where the shoe table may be loaded, I don't want the laces table to load with info about laces.
The issue I'm running into is that there is an attempt to store a duplicate shoe table to the database even though this was only loaded to allow the user to view these details. I imagine that this is because, I'm using [JsonIgnore] attributes to ignore certain parts of the object - it is thus recognizing this as a new object, when it isn't.
I could loop through the object removing any shoe information before call Add, but this would be slow.
Perhaps it is best to post a second object that only includes the items that have changed (after tracking these in the front end). Is there a better way?
When you use DbSet<T>.Add() in EF, the entity (or all the entitis in the tree, if it's an entity with related child entities) is attached to the DbContext as Added. That means that when you call SaveChanges EF will try to insert all the objects in the database. That's why you're getting duplication problems.
You need to learn how to work in disconnected mode with EF. Basically you need to track the state of each entity (i.e. control if they have to be inserted, deleted or updated), and set the correct state when you attach the entities in the context.
Look for docs on working with disconnected entities in EF, for example:
Persistence in Entity Framework
Add, Attach and Entity States
These will explain you how to handle disconnected entities.
I have an odd situation. I am working on a project with a very large existing database that is completely unrelated, but does contain corresponding table id's. It's as if someone copied the database but never related the tables.
In Entity Framework, is there a way to go EF code first and create the relationships in code, but Not apply those relationships in the database? I would like to go through and relate the database but the client doesn't want to pay to fix it.
Thanks!
In this instance, it seems you would be best to add relationships directly to your database (or to a duplicated database for testing/staging) and then just update your entities using your test connection and regression test your app.
I want to create a dynamic datadriven application for practice purposes.
If I have a Modell with a Entity and I need a new one, then I want to create it only in the Diagram (modell) and thats all.
Everything else should be done dynamically, adding the new entity to b.e a Listbox, make it clickable and create a "Show Datas" and a "New/Edit" Tab with the right labels and textboxes in it. (For editing/creating new)
What I would like to know is, how can I:
Get the number of the entities
Is it possible to update the database, without needing to delete it and create new (Else I would loose all Data), if hopefully yes, how?
Get all the fields from a Entity? (Do I must work here with Reflection?)
Hope someone could help
1.Get the number of the entities
Using Context object you get the list of entities. there you can use the .Count() to check the no of entities of that type.
2.Is it possible to update the database, without needing to delete it and create new (Else I would loose all Data), if hopefully yes, how?
This question is little unclear. you want to delete database.. or entity?? you can do any operation on entities that will be reflected on back end if you want. Regarding database delete and create operation, entity framework is not designed for.
Yes you can add new entity to model and then map it with the back end tables.. it is possible to modify the model as per your backend. Even you can create you custom entites that reflect operation on multiple tables on the database but with some care about data integration.
3.Get all the fields from a Entity? (Do I must work here with Reflection?)
Yes.. To access the properties of Entity with out knowing their name you should go through reflection.
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