Entity Framework Code First: отношения "один ко многим" и "многие ко многим" в одну таблицу
У меня есть модель User и модель Event в моем проекте. У события есть создатель (Пользователь) и участник (Пользователи), поэтому у события есть отношения "один ко многим" с пользователем, а также отношение "многие ко многим" к одной и той же таблице.
У меня сначала были отношения "один ко многим" :
Public class Event
{
...
public int CreatedById { get; set; }
public virtual User CreatedBy { get; set; }
...
}
Затем, когда я добавил отношения "многие ко многим" , миграция не создает отношения "многие-многие":
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; }
...
}
Если я удалю отношения "один ко многим" , то миграция успешно создает отношения "многие ко многим" .
Есть ли способ сделать это только с аннотациями данных?
Ответы
Ответ 1
EF не знает, где должно быть сопоставлено User.Events
. Это может быть Event.CreatedBy
, или оно может быть Event.Users
. Оба они приведут к действительной модели. Вы должны дать EF небольшой намек на то, что вы хотите, применив атрибут [InverseProperty]
:
public class User
{
...
[InverseProperty("Users")]
public virtual ICollection<Event> Events { get; set; }
...
}
Ответ 2
С первым подходом кода я всегда рекомендую использовать свободный API, а не использовать DataAnnotations, который автоматически использует некоторые преобразования.
Таким образом, вы узнаете, какую именно конфигурацию вы сделали.
Если бы я был вами, вот что я буду использовать:
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.
}
}