Модель связных таблиц
модель City
public class City
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public Country Country { get; set; }
}
модель Country
public class Country
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
Модель Advertisement
public class Advertisement
{
public int Id { get; set; }
[Required(ErrorMessage ="incorrect information")]
public string Title { get; set; }
[Required]
public string Description { get; set; }
public string Photo { get; set; }
public Country Country { get; set; }
public City City { get; set; }
}
Контекст
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<City>()
.HasOne(p => p.Country)
.WithMany()
.OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<Advertisement>()
.HasOne(p => p.Country)
.WithMany()
.OnDelete(DeleteBehavior.SetNull);
}
Контекст позволяет при удалении Country set NULL в в поля CountryId в таблицы Countries и Advertisements
Вопрос: Необходимо при удаление поля из Countries удалять связные Cities и SetNuLL в поля CityId и CountryID в таблицу Advertisement
У вас отношение один-ко-многим оформлено не полностью:
public class Advertisement
{
public int Id { get; set; }
[Required(ErrorMessage ="incorrect information")]
public string Title { get; set; }
[Required]
public string Description { get; set; }
public string Photo { get; set; }
public int CountryId { get; set; }
public Country Country { get; set; }
public int CityId { get; set; }
public City City { get; set; }
}
У одного города может быть много адверток:
public class City
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int CountryId { get; set; }
public Country Country { get; set; }
public virtual ICollection<Advertisement> Advertisements { get; set; }
}
У одной страны может быть много адверток и много городов:
public class Country
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Advertisement> Advertisements { get; set; }
public virtual ICollection<City> CountryCities { get; set; }
}
И вот когда вы выпишите эти связи - можно будет переходить и более подробно указывать связи и действия при удалении.
Сравните то, что у вас и что у меня:
builder.Entity<City>()
.HasOne(p => p.Country)
.WithMany(p => p.CountryCities)
.HasForeignKey(x => x.CountryId)
.OnDelete(DeleteBehavior.Cascade);
builder.Entity<Advertisement>()
.HasOne(p => p.Country)
.WithMany(p => p.Advertisements)
.HasForeignKey(x => x.CountryId)
.OnDelete(DeleteBehavior.SetNull);
builder.Entity<Advertisement>()
.HasOne(p => p.City)
.WithMany(p => p.Advertisements)
.HasForeignKey(x => x.CityId)
.OnDelete(DeleteBehavior.SetNull);
Документация по теме:
Как это вообще читается. Запомним термины:
В связи один-ко-многим principal/основной сущностью является та, которая "одна", а dependent/зависимой - та, которых "много":
Когда вы ставите точку после modelBuidler вы указываете всегда основную/родительскую сущность:
builder.Entity<City>()
.HasOne(p => p.Country)
.WithMany(p => p.CountryCities)
.HasForeignKey(x => x.CountryId)
.OnDelete(DeleteBehavior.Cascade);
То есть:
Сущность Город
Находится в одной конкретной Стране
У которой много Городов
При удалении основной сущности (Город)
Произвести удаление дочерних сущностей (Страна) по внешнему ключу ИдГород
В качестве примера (ваш посложнее будет) возьмите из документации (ссылка выше) пример Blog < -- > Post, код этого примера лежит на гитхабе:
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder
.Entity<Blog>()
.HasMany(e => e.Posts)
.WithOne(e => e.Blog)
.OnDelete(DeleteBehavior)
.IsRequired(RequiredRelationship);
Пример удаления блога:
var blog = context.Blogs.Include(b => b.Posts).First();
var posts = blog.Posts.ToList();
DumpEntities(" After loading entities:", context, blog, posts);
context.Remove(blog);
DumpEntities($" After deleting blog '{blog.BlogId}':", context, blog, posts);
try
{
Console.WriteLine();
Console.WriteLine(" Saving changes:");
context.SaveChanges();
DumpSql();
DumpEntities(" After SaveChanges:", context, blog, posts);
}
catch (Exception e)
{
DumpSql();
Console.WriteLine();
Console.WriteLine($" SaveChanges threw {e.GetType().Name}: {(e is DbUpdateException ? e.InnerException.Message : e.Message)}");
}
Пошаговые действия:
After loading entities:
Blog '1' is in state Unchanged with 2 posts referenced.
Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
After deleting blog '1':
Blog '1' is in state Deleted with 2 posts referenced.
Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
Post '1' is in state Unchanged with FK '1' and reference to blog '1'.
Saving changes:
DELETE FROM [Posts] WHERE [PostId] = 1
DELETE FROM [Posts] WHERE [PostId] = 2
DELETE FROM [Blogs] WHERE [BlogId] = 1
After SaveChanges:
Blog '1' is in state Detached with 2 posts referenced.
Post '1' is in state Detached with FK '1' and no reference to a blog.
Post '1' is in state Detached with FK '1' and no reference to a blog.
И ещё. У вас структура базы не находится в третьей нормальной форме (3NF), у вас избыточная структура: на Advertisement достаточно указать City, но не указывать Country -- потому что зная City можно сделать .Include к Country.
Подумайте над этим, вполне вероятно, что вам и не нужна такая структура, в которой легко запутаться с непривычки.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Я не смог себе поставить browscap на php72 серевер nginx browscap
Задача такая есть база данных SQL для которой нужно написать php код который будит "определять товар, количество которого больше всего на складе,...
Делаю парсер информации с одного сайтаНужную информацию спарсил, но теперь не могу разбить эту информацию на элементы в массиве