#c# #entity-framework #ef-code-first
#c# #entity-framework #ef-code-first
Вопрос:
Используя парадигму Entity Framework Code First, я определил следующие объекты и взаимосвязи как часть ASP.Net Приложение MVC3. Проблема в том, что связь «многие ко многим» между объектами Photo и Gallery не работает должным образом.
В настоящее время галерея может содержать много фотографий — это правильно. Но фотография может быть связана только с одной галереей — это неверно. Я хочу, чтобы фотография могла быть во многих галереях. Если я добавляю фотографию в галерею, когда она уже связана с другой галереей, она удаляется из другой галереи.
Я был бы очень признателен за ваши решения о том, как заставить работать это отношение «многие ко многим».
Вот мой код:
public class Photo
{
public int ID { get; set; }
public string Title { get; set; }
public virtual ICollection<Gallery> Galleries { get; set; }
}
public class Gallery
{
public int ID { get; set; }
public string Title { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
/* I would expect the following to cause a lookup table to
* be created but it isnt */
modelBuilder.Entity<Photo>().HasMany<Gallery>(p => p.Galleries);
modelBuilder.Entity<Gallery>().HasMany<Photo>(g => g.Photos);
}
Я использую следующий код в моем собственном инициализаторе пользовательской базы данных.
public void InitializeDatabase(PhotoDBContext context)
{
var dbCreationScript = ((IObjectContextAdapter)context).ObjectContext.CreateDatabaseScript();
Log(dbCreationScript);
context.Database.ExecuteSqlCommand(dbCreationScript);
}
Регистрируя переменную dbCreationScript, я вижу, что соответствующий sql, который генерируется для этих таблиц, выглядит следующим образом.
create table [dbo].[Galleries] (
[ID] [int] not null identity,
[Title] [nvarchar](max) null,
[Photo_ID] [int] null,
primary key ([ID])
);
create table [dbo].[Photos] (
[ID] [int] not null identity,
[Title] [nvarchar](max) null,
[Gallery_ID] [int] null,
primary key ([ID])
);
alter table [dbo].[Photos] add constraint [Gallery_Photos] foreign key ([Gallery_ID]) references [dbo].[Galleries]([ID]);
alter table [dbo].[Galleries] add constraint [Photo_Galleries] foreign key ([Photo_ID]) references [dbo].[Photos]([ID]);
Как вы можете видеть, нет SQL, сгенерированного для создания таблицы поиска, что, вероятно, и является причиной того, что связь не работает — почему не создается таблица поиска?
Комментарии:
1. Идентификатор элемента должен быть назван Class ID, например, PhotoID и GalleryId. Это может помочь. Как вы можете видеть в скриптах db, он добавил pk для таблиц.
Ответ №1:
Я считаю, что вам нужно использовать что-то вроде этого:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Photo>()
.HasMany<Gallery>(x => x.Galleries)
.WithMany(x => x.Photos)
.Map(x =>
{
x.MapLeftKey("ID");
x.MapRightKey("ID");
x.ToTable("GalleryPhotos");
});
}
Комментарии:
1. Использование «ID» в качестве имени поля как для MapLeftKey, так и для MapRightKey вызвало проблемы, поэтому я изменил его на
x.MapLeftKey("PhotoID"); x.MapRightKey("GalleryID");
. В остальном идеальное решение. Большое спасибо @Ken Pespisa.2. Существует условие, при котором даже это не решит проблему. У меня было два отношения «многие ко многим» в одних и тех же таблицах, одно для списка элементов по умолчанию и одно для списка элементов экземпляра. Мне пришлось создать другую коллекцию элементов (фотографии в этом примере, например [ICollection<> DefaultPhotos]). Затем в моем втором сопоставлении «многие ко многим» я использовал «WithMany(x => x.DefaultPhotos). Затем моя ошибка исчезла.