Entity Framework: WillCascadeOnDelete и Включить - PullRequest
1 голос
/ 07 мая 2020

У меня такая модель базы данных:

class User
{
    public int ID { get; set; }
    public string Username { get; set; }
    public virtual ICollection<Order> Orders { get; set; }
}
class Order
{
    public int ID { get; set; }
    public string OrderName { get; set; }
    public virtual User User { get; set; }
}

Мои modelBuilder конфигурации выглядят так:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>().ToTable("Users", "dbo");
    modelBuilder.Entity<User>().HasKey(x => x.ID);
    modelBuilder.Entity<User>().Property(x => x.Username).IsRequired();
    modelBuilder.Entity<User>().HasMany(x => x.Orders).WithRequired(x => x.User).WillCascadeOnDelete(true);

    modelBuilder.Entity<Order>().ToTable("Orders", "dbo");
    modelBuilder.Entity<Order>().HasKey(x => x.ID);
    modelBuilder.Entity<Order>().Property(x => x.OrderName).IsRequired();
    modelBuilder.Entity<Order>().Property(x => x.UserID).IsRequired();
}

sql для таблицы dbo.Orders выглядит так:

CREATE TABLE dbo.Orders (
    ID int NOT NULL PRIMARY KEY IDENTITY(1, 1),
    OrderName nvarchar(256) NOT NULL,
    UserID int NOT NULL,

    CONSTRAINT FK_Orders_Users FOREIGN KEY (UserID) REFERENCES dbo.Users (ID) ON DELETE CASCADE
);

В профилировщике сервера sql я вижу, что при выполнении:

dbContext.Users.Remove(dbContext.Users.Include(x => x.Orders).First(x => x.ID == 1));

EF удаляет все заказы отдельно перед удалением пользователя. Я думал, что EF полагается на ON DELETE CASCADE, указанный во внешнем ключе сервера SQL при установке WillCascadeOnDelete(true) (что является поведением по умолчанию для отношений в EF).

Почему EF действует так и как я могу узнать EF, что не нужно удалять Order s перед удалением User?

Ответы [ 2 ]

0 голосов
/ 08 мая 2020

Если у вас есть зависимые сущности, загруженные в трекер изменений, EF применит каскадное поведение в SaveChanges ().

Поведение при удалении, настроенное в модели EF Core, применяется только тогда, когда основная сущность удаляется с помощью EF Core, а зависимые сущности загружаются в память (то есть для отслеживаемых иждивенцев). В базе данных необходимо настроить соответствующее каскадное поведение, чтобы гарантировать, что к данным, которые не отслеживаются контекстом, применено необходимое действие. Если вы используете EF Core для создания базы данных, это каскадное поведение будет настроено для вас.

https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete#delete -behaviors

Если вы этого не сделаете хотите этого, тогда не получайте заказы. Вместо этого просто создайте нового пользователя-заглушки и удалите его.

var stubUser = new User() {ID = 1};
dbContext.Users.Remove(stubUser);
dbContext.SaveChanges();
0 голосов
/ 08 мая 2020

Вы можете удалить эти соглашения о каскадном удалении, используя:

//Remove cascade delete conventions 
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

■ В приведенном выше примере EF применяет набор соглашений (соглашение применяется ко всем вашим объектам) при построении модель, и вы можете переопределить соглашения с помощью плавной конфигурации или атрибутов, как показано ниже:

■ Следующий код настраивает требуемую взаимосвязь, а затем отключает каскадное удаление (только для связанной сущности):

modelBuilder.Entity<Course>()
    .HasRequired(t => t.Department)
    .WithMany(t => t.Courses)
    .HasForeignKey(d => d.DepartmentId)
    .WillCascadeOnDelete(false);

Обновление: Если у вас есть данные, относящиеся к FK, на которые может повлиять эта конвенция, вы можете использовать Nullable FK, как показано ниже. Приведенный выше фрагмент кода создаст в базе данных столбец DepartmentId, допускающий значение NULL, поскольку мы использовали тип Nullable<int> (? - это ярлык для Nullable<int>).

public int? DepartmentId { get; set; }

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...