#c# #.net #entity-framework #.net-core
#c# #.net #entity-framework #.net-ядро
Вопрос:
Я совсем новичок в .NET Entity Framework и в настоящее время я застрял, когда пытаюсь реализовать некоторые отношения между двумя объектами. Я получаю следующее сообщение об исключении:
Не удалось определить связь, представленную свойством навигации ‘Actor.ActiveMovies’ типа ‘ICollection’
Я не знаю, как я правильно определяю эту связь. Объекты movie и actor показаны ниже.
Сущность Movie.cs
public class Movie
{
[Key]
public Guid MovieId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string ThumbnailUrl { get; set; }
public string Language { get; set; }
[Required]
public virtual ICollection<Actor> Actors { get; set; }
}
Объект Actor.cs
public class Actor
{
[Key]
public Guid ActorId { get; set; }
public string ProfileImageUrl { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BornDate { get; set; }
public virtual ICollection<Movie> ActiveMovies { get; set; }
}
Чего я хочу достичь
Кажется, что фильмы и актеры имеют отношение «многие ко многим», поскольку в фильме может быть несколько актеров, а актер может быть активным в нескольких фильмах. Хотя я ничего не придумал для этого.
Что я пробовал
Я проверил DatabaseContext и подумал, что смогу реализовать многие для многих следующим образом.
modelBuilder.Entity<Movie>(entity =>
{
entity.HasKey(movie => movie.MovieId);
entity.Property(movie => movie.Actors).IsRequired();
entity.HasMany<Actor>(movie => movie.Actors);
});
modelBuilder.Entity<Actor>(entity =>
{
entity.HasKey(actor => actor.ActorId);
entity.HasMany<Movie>(actor => actor.ActiveMovies);
});
Но это дало мне сообщение об исключении
Свойство или навигация ‘Actors’ не могут быть добавлены к типу объекта ‘Movie’, поскольку свойство или навигация с тем же именем уже существуют для типа объекта ‘Movie’.
Я был бы признателен за любую информацию в этом случае!
Комментарии:
1. Для отношения «многие ко многим» требуется таблица распределения вместо списков, и вы ссылаетесь на нее как actorID, так и MovieID (с другими столбцами, если хотите, например, имя сыгранного персонажа, роль, что угодно). С помощью этого вы можете создать несколько записей для одного и того же фильма (разных актеров), и один и тот же актер может быть в нескольких фильмах. Это может быть личным, но я предпочитаю создавать новую сущность, чем использовать списки и работать с ModelBuilder.
Ответ №1:
Вам необходимо полностью определить взаимосвязь. В этом случае мы используем отдельную таблицу. Попробуйте это.
public class Movie
{
public Guid MovieId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string ThumbnailUrl { get; set; }
public string Language { get; set; }
public virtual ICollection<MovieActor> MovieActors { get; set; }
}
public class Actor
{
public Guid ActorId { get; set; }
public string ProfileImageUrl { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BornDate { get; set; }
public virtual ICollection<MovieActor> MovieActors { get; set; }
}
public class MovieActor
{
public int MovieId { get; set; }
public Movie Movie { get; set; }
public int ActorId { get; set; }
public Actor Actor{ get; set; }
}
и в вашем OnModelCreating()
modelBuilder.Entity<MovieActor>()
.HasKey(x=> new { x.ActorId, x.MovieId });
modelBuilder.Entity<MovieActor>()
.HasOne(bc => bc.Movie)
.WithMany(b => b.MovieActors)
.HasForeignKey(bc => bc.MovieId);
modelBuilder.Entity<MovieActor>()
.HasOne(bc => bc.Actor)
.WithMany(c => c.MovieActors)
.HasForeignKey(bc => bc.ActorId);
Комментарии:
1. Я бы добавил определенный идентификатор (или Guid) в
MovieActor
таблицу и удалил обе ICollections.2. Это тоже правильно ! , Но исправил код по своему стилю. Это также будет работать.
3. Ах, хорошо, что это работает таким образом. Я собираюсь протестировать это завтра. Нужен ли новому объекту как объект Movie, так и MovieID? Или это ошибка во фрагменте кода?
4. Конечно, для этого нужны как объект Movie, так и MovieID. Это основной момент создания отношений «многие ко многим».
Ответ №2:
Ядро EF, к сожалению, пока не поддерживает отношения «многие ко многим», не требуя отношения как полностью определенной сущности.
Появление в .net 5 и EF core 5.x — это та функция, которая будет примерно работать как
builder.Entity<Movie>()
.HasMany(m=>m.Actions)
.WithMany(a=>a.Movies); // Invented syntax, the feature has not been released yet.
На данный момент вам нужно будет определить объект, который отображает MovieActor вручную, и сопоставить обе стороны отношения «один ко многим», которое он будет моделировать. Я исключаю определение для этой сущности здесь, просто собираюсь определить конфигурацию ниже.
builder.Entity<MovieActor>()
.HasKey(ma => new { ma.MovieId, ma.ActorId });
builder.Entity<Movie>()
.HasMany(m=>m.MoiveActors)
.WithOne(ma=>ma.Movie);
builder.Entity<Actor>()
.HasMany(m=>m.MoiveActors)
.WithOne(ma=>ma.Actor);