I have a User model and a Event model in my project. The Event has a creator(User) and has participant(Users) so Event has a one-to-many relationship with User and also a many-to-many relationship to the same table.
I had first the one-to-many relationship like this:
Public class Event
{
...
public int CreatedById { get; set; }
public virtual User CreatedBy { get; set; }
...
}
Then when I added the many-to-many relationship the migration doesn't generate the many to many relationship:
Public class User
{
...
public virtual ICollection<Event> Events { get; set; }
...
}
Public class Event
{
...
public int CreatedById { get; set; }
public virtual User CreatedBy { get; set; }
public virtual ICollection<User> Users { get; set; }
...
}
If I remove the one-to-many relationship then the migration generates the many-to-many relationship successfully.
Is there a way to do this with only data annotations?
EF doesn't know where User.Events has to be mapped to. It could be Event.CreatedBy or it could be Event.Users. Both would result in a valid model. You must give EF a little hint what you want by applying the [InverseProperty] attribute:
public class User
{
...
[InverseProperty("Users")]
public virtual ICollection<Event> Events { get; set; }
...
}
With Code First Approach, I would always recommend to use fluent API rather than using DataAnnotations, Which uses some conversions automatically.
This way, you'll know what exact configuration you've made.
If I were you, here is what i would use :
public class EventMap : EntityTypeConfiguration<Event>
{
public EventMap()
{
this.HasRequired(m => m.CreatedBy) // envent must have a creator
.WithMany() // a user can have 0,1 or more events created by him
.HasForeignKey(m => m.CreatedById) // specify property to be used as FK
.WillCascadeOnDelete(true); // delete all events created by user if that specific user is deleted
this.HasMany(m=>m.Users) // an event can have 0,1 or more participants
.WithMany(m=>m.Events) // a user can be a participant in 0,1 or more events
.Map(m => m.MapLeftKey("EventId").MapRightKey("UserId")); // this will generate intermediate table to hold participant information - dbo.EventUser with EventId & UserId
// Cascade Delete is always true for Many to Many mapping. however, it doesn't delete entry in other table, it deletes entry in Joined Table only.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With