Каким образом каскадные удаления идут в отношениях «один ко многим»?

Использование подхода Entity Framework, основанного на коде.

Предположим, у меня есть два класса сущностей:

[Table("Objects")]
public class DbObject : IValidatableObject
{
    public long Id { get; set; }

    public string Name { get; set; }
    public string Description { get; set; }

    public virtual ICollection<DbObjectProperty> Properties { get; set; }
}

[Table("ObjectProperties")]
public class DbObjectProperty
{
    public long Id { get; set; }

    public string Name { get; set; }
    public string Value { get; set; }

    [Display(Name = "Object"), UIHint("Object")]
    public long ObjectId { get; set; }
    public virtual DbObject Object { get; set; }
}

Здесь следует отметить:

  • DbObject имеет только свойство навигации, но не столбец с внешним ключом
  • DbObjectProperty имеет свойство навигации и соответствующий столбец с внешним ключом
  • Должно быть очевидно, что если я удаляю объект, я хочу, чтобы его свойства сохранялись вместе с ним, но если я удаляю одно свойство, я не хочу, чтобы весь объект исчезал.

В методе OnModelCreating для контекста БД до сих пор у меня было следующее для определения отношения:

modelBuilder.Entity<DbObjectProperty>()
    .HasRequired(op => op.Object)
    .WithMany(obj => obj.Properties)
    .HasForeignKey(op => op.ObjectId)
    .WillCascadeOnDelete(false);

Конечно, это означает, что каскадных удалений не произойдет. Мой вопрос: если я изменю это на true, будет ли это делать то, что я хочу? Помните, что если я удаляю объект, я хочу, чтобы его свойства сохранялись вместе с ним, но если я удаляю одно свойство, я не хочу, чтобы весь объект исчез.

Автоматически сгенерированный код миграции для этого изменения (с false на true) выглядит следующим образом:

DropForeignKey("ObjectProperties", "ObjectId", "Objects");
DropIndex("ObjectProperties", new[] { "ObjectId" });
AddForeignKey("ObjectProperties", "ObjectId", "Objects", "Id", cascadeDelete: true);
CreateIndex("ObjectProperties", "ObjectId");

Я обеспокоен тем, что это, по-видимому, означает, что удаление свойства приведет к удалению связанного с ним объекта. Будет ли он?


person Timwi    schedule 12.04.2012    source источник


Ответы (1)


Направление каскадного удаления отношения в базе данных определяется тем, что является главным (таблица первичного/уникального ключа) и чем является зависимым (таблица внешнего ключа) этого отношения.

Затем, если вы удаляете принципала, все зависимые элементы, значение внешнего ключа которых соответствует значению первичного/уникального ключа этого принципала, также удаляются. Нет каскадного удаления в направлении от зависимого к основному.

В вашем случае принципалом является DbObject, а зависимым - DbObjectProperty, потому что это сущность/таблица с внешним ключом.

Каскадное удаление наоборот — редко имеет смысл, особенно в отношениях «х-ко-многим»: если вы удалите зависимого (DbObjectProperty), а основной (DbObject) будет удален автоматически, ограничение внешнего ключа будет нарушено. если есть какие-либо другие зависимые ссылки на принципала, который будет удален.

Вам не нужно беспокоиться.

person Slauma    schedule 12.04.2012
comment
Эмпирическое правило заключается в том, что при каскадном удалении, если удаление записи нарушает внешний ключ из другой записи, эта зависимая запись также удаляется. - person orad; 30.09.2015
comment
Итак, modelBuilder.Entity<Parent>().HasMany(p => p.Children).WithOne(c => c.Parent) совпадает с modelBuilder.Entity<Child>().HasOne(c => c.Parent).WithMany(p => p.Children) (они определяют одно и то же отношение)? - person Peppe L-G; 23.09.2016