Search code examples
c#sql-serverentity-framework-6many-to-many

How to handle self references in Entity Framework code-first?


These are my models (simplified):

public User()
{
        Friends = new HashSet<User>();
        Subscriptions = new HashSet<Subscription>();
        Tasks = new HashSet<Task>();
        Invitations = new HashSet<Invitation>();
        Events = new HashSet<Event>();
}

public Guid UserId { get; set; }
public DateTime MemberSince { get; set; }

[StringLength(450)]
[Index("UserNameIndex", IsUnique = true)]
public string NickName { get; set; }

public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAdress { get; set; }        
public string HashedPassword { get; set; }

public virtual ProfilePicture ProfilePicture { get; set; }

public bool Validated { get; set; } 

ICollection<Event> Events { get;  set; }
ICollection<User> Friends { get;  set; }

And the Event model:

public class Event
{    
    public string EventName { get; set; }
    public Guid EventId { get; set; }
    public Guid UserId { get; set; } 
    public DateTime? Time { get; set; }
    public string Location { get; set; }
    public DateTime? EventDate { get; set; }        
    public virtual User User { get; set; }

    public ICollection<User> Participants { get; internal set; }        
}

Here's the model creation:

modelBuilder.Entity<User>().HasKey(u => u.UserId);
modelBuilder.Entity<User>().
             HasMany<User>(u => u.Friends).
             WithMany();

modelBuilder.Entity<User>().
             HasMany<Event>(u => u.Events).
             WithMany();

Now the problem is the following: my tables look like this:

It seems like the relations are not the way they should be...

User table:

enter image description here

Event table:

enter image description here

Automatically created UserEvents:

enter image description here

Now what I expected is when creating a new Event (UserId) is required there. I get a new Entry in the Events table + a new one in the UserEvents....

What am I missing here ?


Solution

  • You have two different relations between User and Event. A one-to-many relation and a many-to-many relation.

    The first is a one-to-many relationship between the event and the creator of the event (The user and userid properties on Event) When you add a new Event with the required UserId, there will not be a record created in the automatically created UserEvents table, because you have a one-to-many relationship here. So simply creating an Event with the userid will not lead to a record in the UserEvents table.

    The second is the many-to-many relationship between Event and it's participants. When you add an event with participants. There would be records also inserted into the UserEvents table. Only participants will appear in the UserEvents table. You should however create your many-to-many mapping with a reference to your property Participants in the Event class to make this possible.

    modelBuilder.Entity<User>().HasMany<Event>(u => u.Events).WithMany(m => m.Participants);