ef core 2.2: Ho to setup cascade delete with foreign key in dependant - foreign-keys

I've set up a code first db with some base entities like "Participant", "Organizer" or "School". They all may have a dependant child entity called "Person". Because such Persons may belong to any of these main entities, the main entities hold a foreign key "PersonId" and a navigation property "Person".
But as far as I know EF decides by location of the foreign key which entity is dependant – in this case the main entities – and which is principal – in this case "Person".
Accordingly cascade delete does not work as I need it: deleting a "Participant" should delete its "Person".
I annotated the "Person" properties with [Required] and indeed the DB states that "PersonId"-columns are decorated with a cascade-delete-constraint:
CONSTRAINT FK_Participants_Persons_PersonId FOREIGN KEY (PersonId) REFERENCES Persons (Id) ON DELETE CASCADE
But removing the main entity (with eager loaded person) and calling SaveChanges does not delete the person.
So how could I achieve Persons are deleted on delteig their main entities?

As Ivan mentions in a comment:
What you are describing looks more like TPT inheritance model, which is not currently supported. There is no automatic way to cascade delete in the opposite direction - this comes from relational database rules and has nothing to do with EF Core. So even with the TPT, the deletion of the derived entity will be redirected to deleting the base entity. Simply do the same - instead of deleting (dbContext.Remove) the Participant, Organizer or School instances, delete (Remove) their loaded Person navigation property.

Related

Google Datastore: how to retrieve entities with children?

I only found the way to get children entities by parent one.
But is there any way to retrieve the list of parent entities (by some parent entity's properties filter) with their children in single call?
(Pseudo query):
SELECT * FROM parents (with children) WHERE parent.property1=...
Result should be like this:
- (parent1, child1, child2)
- (parent2, child3, child4)
....
This is not possible if you store the parents and children as separate entities. However, if the children for a parent is expected to be small, then you can consider storing them as embedded struct slice. Then as you query the parent entities and retrieve them you will have access to their children.
The short answer is no.
Some background
Entities in a Datastore mode database form an ancestor path, which means a hierarchically structured space, similar to the directory structure of a file system.
Workarounds:
Depending on your needs there are a couple things that you could do:
You could retrieve each parent and their children individually in multiple calls and then combine all the parts together.
You could use Special query types, such as kindless queries, which is a query with no kind and no ancestor filter that retrieves all of the entities of an application from Datastore, so you can gather the needed information.
Not sure this qualifies as an answer but I have the same scenario and below are the two options I am considering.
The scenario I am in is an Employer kind and an Employee kind. The Employee is a child of Employer but the same Employee can be part of multiple Employers.
I need to find all Employers a specific Employee is part of.
Option 1 (the one I think I will go with)
Have a third entity for a reverse lookup. The key will be the Employee's last part of the key with an additional property to hold the list of Employers' keys.
Every time an Employer/Employee relationship changes I will also update the reverse lookup kind.
Option 2
Have the last part of the Employee's key saved separately in the same entity as an indexed property so that I can search by it (and then able to find each of those entities' parent key).

Creating User Generated Models and SQL Tables in Ruby on Rails 4

Considering scenario of an Inventory Management System. Inventory has many types of items, each with own table and columns. One, two or Twelve tables are not sufficient to describe the plethora of the TYPES of items as they are extremely varying. e.g. some attributes of a family of items like BIKES do not have the same attributes of CARS. It is tedious for developer to take into account the thousands of the TYPES of items and incorporate them into each model manually.
Is there a way for users to generate models themselves? thereby generating own SQL tables etc... Is there another approach to this problem? (Maybe using Semantic Web Technologies)
Coming from Spring Framework, I am fairly new to RoR development.
Thanks in Advance.
I'm not an expert, but you could do it with regular, pre-defined models.
Item_Type
Item_Attribute
Item
Item_Type would have a name variable (not unique), and perhaps any other common attributes you'd want. It would then have a has_many Item_Attributes relationship, whereas Item_Attribute belongs_to Item_Type.
So I'd make a view that allows the user to add new Item_Types and then define Item_Attributes for those item types.
Then you could have the actual Item model, each instance of which is the existence of an Item_Type in the inventory. Item belongs to Item_Type, and Item_Type has_many Items, and Item cannot have a null Item_Type.
So a user creates a new Item_Type with the name "BIKE", then adds several Item_Attributes to it, such as "Mountain" and "Red". Then the user can create a new Item that has a relationship to the "BIKE" Item_Type.
If they wanted to add a blue mountain bike instead of a red one, they would need to go through the process again, adding another Item_Type of "BIKE" except adding "Blue" as an attribute for the new instance of Item_Type's Item_Attributes.

Entity Framework Cascade Deleting, even though no CASCADE set up in database

I have a foreign key relationship between two tables UserProducts and Users in my database, with UserProducts having a UserID referencing the UserID in the Users table.
ALTER TABLE [dbo].[UserProducts] WITH CHECK ADD CONSTRAINT [FK_UserProducts_Users] FOREIGN KEY ([UserID])
REFERENCES [dbo].[Users] ([UserID])
GO
ALTER TABLE [dbo].[UserProducts] CHECK CONSTRAINT [FK_UserProducts_Users]
GO
The UserID column in the UserProducts table is part of a composite primary key with another column ProductID. There are also two additional DateTime columns, so Entity Framework does not treat UserProducts as a link table.
There is NO cascade delete on that foreign key above, nor did I set up anything to handle OnDelete on the Entity Framework foreign key association. Yet, when I delete a User entity from code, Entity Framework is taking the liberty of deleting the UserProducts associated with it by UserID. It is also generating a lot of SQL to do it: there is a separate DELETE per related record in the UserProducts table.
The code to perform the entity deletion is as follows:
using (var context = new LicensingRegistrationContext(_csb))
{
context.Database.Log = a => _logger.Trace(a);
var dbUser = GetUserDbSetWithIncludes(context)
.Where(a => a.UserID == user.Id).Single();
context.DbUsers.Remove(dbUser);
//TODO(MRL): Um...how are the dbUserProducts being removed???
context.SaveChanges();
}
How is this happening? In EF 4 I am pretty sure EF never took this liberty of doing this: you HAD to load and then delete all related entities manually in code.
Thanks
Entity framework by default has a
OneToManyCascadeDelete
convention. Here is the link http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions.onetomanycascadedeleteconvention(v=vs.113).aspx
So entity framework cascade deletes the one to many relationship by default.
You can disable this by disabling the convention or explicitly disabled it for this relationship via the fluent API.
I found this on MSDN and I believe this is what is happening:
When a primary key of the principal entity is also part of the primary key of the dependent entity, the relationship is an identifying relationship. In an identifying relationship the dependent entity cannot exist without the principal entity. This constraint causes the following behaviors in an identifying relationship: Deleting the principal object also deletes the dependent object. This is the same behavior as specifying OnDelete Action="Cascade" in the model for the relationship. Removing the relationship deletes the dependent object. Calling the Remove method on the EntityCollection marks both the relationship and the dependent object for deletion.
This is what is happening in my model where the UserComponent table has a composite primary key: UserID, ComponentID and the UserID column is a foreign key to the UserID in the User table.

Adding Entity with Many-To-One association and inverse side already existing in the database

Using Doctrine 2 with Zend Framework 2. Been thinking of how I am meant to persist an entity with a field having a Many-To-One association with another entity that already exists in the database. Would I have to fetch the inverse side from the database first and then adding it to the owning Entity before persisting to the database as in the code below.
//$data = $_POST;
$book = new Book();
$author = $em->getRepository('Application\Entity\Book')->find($data['author_id']);
$book->setTitle($data['title'])
->setISBN($data['title'])
->setAbstract($data['abstract'])
->setYear($data['year'])
->setAuthor($author);
$em->persist($book);
$em->flush();
Normally, without using doctrine, all I have to do is update the author_id field of the Book entity above and persist to the Database. But now I have to make a trip to the Database to fetch the author details to create the entity and thus the association and then persist.
Is this the way it should be done or there is another way that doesnt involve fetching the author's details.
As you can read here
The method EntityManager#getReference($entityName, $identifier) lets
you obtain a reference to an entity for which the identifier is known,
without loading that entity from the database. This is useful, for
example, as a performance enhancement, when you want to establish an
association to an entity for which you have the identifier.
You could simply do this:
$book = new Book();
$book->setAuthor( $em->getReference('Application\Entity\Author',$data['author_id']));

Deleting and updating Many-to-Many Relationships using OpenJPA

I have a couple of entities that will be deleted. Those entities will have a couple Many-To-Many links. When updating a many-to-many link I am thinking I will just delete the original links in the joining table for that entity and just replace the link with a new link. But I am really confused on how that would work. How do you update a many-to-many relationship? Same thing goes for delete. If you have cascade for deletes set, then you would essentially delete that entity and the entities (collection, multiple entities I believe) that are linked to it. How would that work?
#Entity
#Table(name="QUICK_LAUNCH")
public class QuickLaunch implements Serializable {
...
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name="QUICK_LAUNCH_PROVIDER",
joinColumns=#JoinColumn(name="QUICK_LAUNCH_ID"),
inverseJoinColumns=#JoinColumn(name="RESOURCE_ID"))
private List<Provider> providerList;
}
The thinking was that I would delete any links to a provider and just add new links. I could do that programatically, just delete links in the linking table, but I feel as though that should be handled by the ORM (is that an unreasonable feeling?).
Does anybody have any general words of wisdom for Deleteing Many-To-Many relationships,
Maybe I could just delete and update relationships using the actual entities...
Like say I have a quickLaunch with a list of providers... I set that list of providers to null (effectively removing that list of providers from that entity I would hope) I would then set that list of providers to a new list of providers... I of course would have to set up that list programatically. Does that sounds feasable or just freaking stupid?
That's the way to do:
removing a provider from the list will remove the association between the QuickLaunch and the provider (and thus delete the corresponding row from the join table);
adding a provider to the list will create the association between the QuickLaunch and the provider (and thus insert a row in the join table).