Problem 1
The answer is pretty simple:
Entity Framework cannot determine cascading deletion when it does not know which properties belong to the relation.
In addition, in many ways, there is a third table that is responsible for managing relationships. This table must have at least 2 FK. You must configure cascading deletion for each FK, not for the entire table.
The solution creates a FriendshipRelation object. Like this:
public class UserFriendship { public int UserEntityId { get; set; }
Now you need to change UserEntity . Instead of a UserEntity set UserEntity it has a UserFriendship set. Like this:
public class UserEntity { ... public virtual ICollection<UserFriendship> Friends { get; set; } }
Let's look at the display:
modelBuilder.Entity<UserFriendship>() .HasKey(i => new { i.UserEntityId, i.FriendEntityId }); modelBuilder.Entity<UserFriendship>() .HasRequired(i => i.User) .WithMany(i => i.Friends) .HasForeignKey(i => i.UserEntityId) .WillCascadeOnDelete(true);
Generated Migration:
CreateTable( "dbo.UserFriendships", c => new { UserEntityId = c.Int(nullable: false), FriendEntityId = c.Int(nullable: false), }) .PrimaryKey(t => new { t.UserEntityId, t.FriendEntityId }) .ForeignKey("dbo.UserEntities", t => t.FriendEntityId, true) .ForeignKey("dbo.UserEntities", t => t.UserEntityId, true) .Index(t => t.UserEntityId) .Index(t => t.FriendEntityId);
To get all user friends:
var someUser = ctx.UserEntity .Include(i => i.Friends.Select(x=> x.Friend)) .SingleOrDefault(i => i.UserEntityId == 1);
It all works great. However, there is a problem in this mapping (which is also happening in your current mapping). Suppose "I" is a UserEntity :
- I made a friend request to John - John accepted
- I asked a friend to turn to Ann Ann.
- Richard turned to me with a friend - I accepted
When I get the Friends property, it returns โJohn,โ โAnne,โ but not โRichard.โ What for? because Richard is the "creator" of the relationship, not me. The Friends property is tied to only one side of the relationship.
Ok How can i solve this? Easy! Change the UserEntity class:
public class UserEntity {
Update Cartography:
modelBuilder.Entity<UserFriendship>() .HasRequired(i => i.User) .WithMany(i => i.FriendRequestsMade) .HasForeignKey(i => i.UserEntityId) .WillCascadeOnDelete(false); modelBuilder.Entity<UserFriendship>() .HasRequired(i => i.Friend) .WithMany(i => i.FriendRequestsAccepted) .HasForeignKey(i => i.FriendEntityId) .WillCascadeOnDelete(false);
No migrations required.
To get all user friends:
var someUser = ctx.UserEntity .Include(i => i.FriendRequestsMade.Select(x=> x.Friend)) .Include(i => i.FriendRequestsAccepted.Select(x => x.User)) .SingleOrDefault(i => i.UserEntityId == 1);
Problem 2
Yes, you need to reassemble and delete all child objects. See my answer in this thread Net hierarchy update in Entity Framework
Following my answer, just create a UserFriendship dbset:
public DbSet<UserFriendship> UserFriendships { get; set; }
Now you can get all friends of a specific user ID, just delete all of them with one shot, and then delete the user.
Problem 3
Yes it is possible. You now have a dbset UserFriendship .
Hope this helps!