I want to know about relation dependent destroy and dependent nullify on rails and relation with SQL.
Thanks
Example:
Table users and table cars
user has many cars
car belongs to users
in table car you have user_id on each row
if you set dependent destroy when defining the relationship in users, then when you delete a user, all cars having that user_id will be deleted also
if you set nullify, cars will remain, but the user_id column will be set to null (it is pointless to have any value there because the user with that id was deleted)
Hope that this helps
You use these options when you want to get rid of orphaned records.
Most common used is destroy because it removes all associated objects one by one.
You can use dependent when we want to get rid of orphaned records since they can lead to various problems. Orphaned records are created when we delete or destroy a model A that was associated with model B, but model B wasn't removed in the process.
You most often want to use destroy - all associated objects will remove one by one.
other common options are:
:delete_all – all associated objects will be deleted in a single query.
:nullify – foreign keys will be set to NULL
You can check more details about this here.
Related
For what I searched there are 2 ways to insert an already present record into a ICollection list:
group.Users.Add(db.Users.FirstOrDefault(x=> x.Id = 1));
var to_add = new User{Id: 1}; db.Users.Attach(to_add); group.Users.Add(to_add);
The problem with both the above approach is it makes a db call every time we want to add a record. While we already know the user's Id and the group's id and that's all it needs to create a relationship.
Imagine a long list to be added, both the above methods would make multiple calls to db.
So you have Groups and Users. Every Group has zero or more Users; every User has zero or more Groups. A traditional many-to-many relationship.
Normally one would add a User to a Group, or a Group to a User. However you don't have a Group, nor a User, you only have a GroupId and a UserId. and because of the large number of insertions you don't want to fetch the Users and the Groups of which you want to create relations
The problem is, if you could add the GroupId-UserId combination directly to your junction table, how would you know that you wouldn't be adding a Group-User relation that already exists? If you wouldn't care, you'd end up with twice the relation. This would lead to problems: Would you want them to be shown twice if you'd ask the Users of a Group? Which one should be removed if the relation ends, or should they all be removed?
If you really want to implement the possibility of double relation, then you'd need to Implement a a Custom Junction Table as described here The extra field would be the number of relations.
This would not help you with your large batch, because you would still need to fetch the field from the custom junction table to increment the NrOfRelations value.
On the other hand, if you don't want double relations, you'd have to check whether the value already exists, and you didn't want to fetch data before inserting.
Usually the number of additions to a database is far less then the number of queries. If you have a large batch of data to be inserted, then it is usually only during the initialization phase of the database. I wouldn't bother optimizing initialization too much.
Consider remembering already fetched Groups and Users in a dictionary, preventing them to be fetched twice. However, if your list is really huge, this is not a practical solution.
If you really need this functionality for a prolonged period of time consider creating a Stored Procedure that checks if the GroupId / UserId already exists in the junction table, and if not, add it.
See here For SQL code how to do Add-Or-Update
Entity Framework call stored procedure
I designing a SQL db system(with Postgre) and I have a question about what is the common practice to create a relationship / reference that can persist even when referenced objects are deleted.
For example, there is a UserORM, and ActivityORM, and UserActivityRelation. ActivityORM holds user.id as foreign key to tell who created the activity, and relation table is about which users should know about the activity.
Now, if I want to remove the actor from db, I still want ActivityORM and the relation table to persist so that other users can still know about the activities. I want to know what is the most common / best practice to design such system. Simple answers might be not assigning them as foreign keys, or create an inactive state, but I wonder if there is any better ways. Thank you.
As you mentioned, removing the problematical foreign key constraints would solve the immediate problem of deleting either users or activities on either side of the bridge table. But then this would allow broken relationships to end up in your database.
I propose using soft deletion here. Add an active bit column to both the UserORM and ActivityORM tables. Then, when you need to delete a user or activity, just mark that record as inactive. This would guarantee that the key relationships do not get broken during the deletion. And this approach would also let you view relationships which used to exist, prior to any deletions.
I can't seem to work this out at the moment.
I have 3 tables, interests, interest_user, and users, with a many-to-many relationship setup between them.
If I delete an interest I want to make sure that any records in the pivot table are deleted as well (or else I'm going to run into errors down the line I guess).
Can this be done with $table->foreign() on the interests table (I don't think so because there's no id to reference). Otherwise do I have to loop through all the relationships when the interest is deleted and delete each pivot?
I think I'm going to encounter the same problem on a one-to-many relationship I have
One category has many interests. If I delete a category I don't think I can have a foreign key linked to interests on the category table. I'll also need to cascade a category deletion through to all the interest_user records.
Any guidance would be hugely appreciated as my brain is a little frazzled.
Cheers!
Alex
Many to Many:
According to the Laravel 3 Docs on Foreign Keys, your migration for the pivot table should be:
$table->foreign('user_id')->references('id')->on('users')->on_delete('cascade');
$table->foreign('interest_id')->references('id')->on('interests')->on_delete('cascade');
When you delete either a user or an interest, the rows associated with that user or interested in the pivot table will be deleted.
One to many
If you are dealing with a one-to-many (for example, users and creditcards). on the creditcards table you will have a user_id and to set up foreign key like so:
$table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); (basically exactly like the many-to-many)
So when you delete the user, the row(s) on the creditcards table associated with that user will be deleted as well.
On my site user can make some items and those items goes in Items table.
Users can also follow each other and those data I store in Followings table.
Now I need one table that keep track of user activities, so I have created:
Users{UserId, Username, FirstName, LastName}
Items{ItemId, Title, CreatedByUserId}
Activity{ActivityId, ActivityTypeId, UserId, ItemId}
Here ItemId can be or ItemId from Items table or UserId from Users table.
Is this design good or there is better approach to do this?
Edit: I have added table structures. The point is that I wan't to add record to that Activity table every time when user create item or start to follow some user. So I can always track what user did on the site.
Here ItemId can be or ItemId from Items table or UserId from Users table.
This will prevent the DBMS from enforcing the foreign key. If you go down that route, better separate these fields (so you can make foreign keys towards their respective tables) and use a CHECK to ensure exactly one of them is non-NULL:
CHECK (
(ITEM_ID IS NOT NULL AND FOLLOWED_USER_ID IS NULL)
OR (ITEM_ID IS NULL AND FOLLOWED_USER_ID IS NOT NULL)
)
The ACTIVITY PK is crafted so it is easy to query for a "timeline" of a specific user and is friendly to clustering.
(You may or may not need ACTIVITY.TYPE depending on what exactly you want to track.)
The alternative would be to have a separate table for each kind of activity:
(And you could add a TYPE field in FOLLOW_ACTIVITY to distinguish between "follow" and "unfollow".)
Another alternative would be to inherit users and items from a common parent "class" and then link to that class:
This design is probably an overkill in this case, but could be useful if you later add many other kinds of objects that could be tracked.
Items{ItemID,descr,UserIDCreator,date-time}
User{UserID,descr}
Followings{UserIDFollowed,UserIDFollower,date-time}
now if you wont all items created by eser use user code on items
the same on followings I add date-time for chrono select
You can create atriggered table or a view this depends on cardinality of data
If the same object can be share between users
Items{ItemID,descr,}
UserItems{UserID,descr,ItemId,date-time}
User{UserID,descr}
Followings{UserIDFollowed,UserIDFollower,date-time}
I hope to be useful
I have a many-to-many relationship between the entities Groups and Contacts. One group can have many contacts, and one contact can exist in many groups.
Now If I were to delete a group how should I handle all the references to the contacts that it holds?
As I see it there are two options: to use the nullify rule, that would set the deleted group reference to nil for those contacts that had that group. But this sort of introduces a micro-management problem. I then have to check each time I'm listing a contacts groups if any of the groups are nil.
So for me the more elegant solution would be that when a group is deleted, I would delete the group reference completely(?) from the contact object so that it will not contain any nil values for groups at all. Is that possible?
But this sort of introduces a micro-management problem. I then have to
check each time I'm listing a contacts groups if any of the groups are
nil.
No. See this answer to a similar question. If you set the deletion rule for both the Groups->>Contacts and Contacts->>Groups relationships to nullify, then:
deleting a contact will remove that contact from any groups that include it
deleting a group will remove that group from any contacts that belong to it
Collection objects in the Foundation framework (NSArray, NSSet, etc.) never have "nil values." It is possible to store the NSNull singleton as a value in a collection, but that's not what the nullify deletion rule does.
It sounds like the nullify rule is appropriate for both relationships in your situation. The only thing you need to be concerned about is what should happen when you delete all the contacts that belong to a given group or vice versa. A contact that doesn't belong to any groups makes sense, but what should happen to a group that contains no contacts? If a group with no members doesn't make any sense for your app, you'll have to deal with that case.