Указание ON DELETE NO ACTION в Entity Framework 7?

В Entity Framework 7, когда я пытаюсь применить миграцию, я получаю ошибку

Представление ограничения FOREIGN KEY "FK_ChangeOrder_User_CreatedByID" в таблице "ChangeOrder" может вызывать циклы или несколько каскадных путей. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION или измените другие ограничения FOREIGN KEY.
Не удалось создать ограничение. См. Предыдущие ошибки.

Я знаю, что в более ранних версиях Entity Framework вы справитесь с этим, добавив

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

для DbContext, но в EF7 modelBuilder, похоже, не имеет .Conventions, и google возвращает только старый EF 4, хотя результаты EF 6.

Как определить ограничение ON DELETE NO ACTION в Entity Framework 7?

Изменить: Ответ, предоставленный Олегом, по-видимому, сделает это для внешнего ключа, но я хотел бы сделать это во всем мире, так как гораздо проще использовать одну строку кода для объявления этого глобально, тогда необходимо указать код для каждой из сотен отношения, которые я получаю.

Изменить 2: Код для Олега

public class ChangeOrder
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    public Int16? ApprovedByID { get; set; }
    public Byte ApprovalStatusID { get; set; }
    public Int16 AssignedToID { get; set; }
    public Int16 CreatedByID { get; set; }
    public Byte CurrentStatusID { get; set; }
    public DateTime? DateApproved { get; set; }
    public DateTime? EndDate { get; set; }
    public Byte ImpactID { get; set; }
    public Byte PriorityID { get; set; }
    public DateTime? StartDate { get; set; }
    public Byte TypeID { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string ReasonForChange { get; set; }

    [ForeignKey("ApprovedByID")]
    public User ApprovedBy { get; set; }

    [ForeignKey("ApprovalStatusID")]
    public ChangeApprovalStatus ApprovalStatus { get; set; }

    [ForeignKey("AssignedToID")]
    public User AssignedTo { get; set; }

    [ForeignKey("CreatedByID")]
    public User CreatedBy { get; set; }

    [ForeignKey("ImpactID")]
    public ChangeImpact Impact { get; set; }

    [ForeignKey("PriorityID")]
    public ChangePriority Priority { get; set; }

    [ForeignKey("TypeID")]
    public ChangeType ChangeType { get; set; }

    [ForeignKey("CurrentStatusID")]
    public ChangeStatus CurrentStatus { get; set; }
}
public class JobSightDBContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        base.OnModelCreating(modelbuilder);
    }

    DbSet<ChangeApprovalStatus> ChangeApprovalStatus { get; set; }
    DbSet<ChangeImpact> ChangeImapct { get; set; }
    DbSet<ChangeOrder> ChangeOrders { get; set; }
    DbSet<ChangePriority> ChangePriorities { get; set; }
    DbSet<ChangeStatus> ChangeStatus { get; set; }
    DbSet<ChangeType> ChangeTypes { get; set; }
    DbSet<User> Users { get; set; }
}

Ответ 1

После того, как вы покопались в GitHub и поработали с очень терпеливым парнем из MS, текущее решение - добавить это в DbContext

protected override void OnModelCreating(ModelBuilder modelbuilder)
{
    foreach (var relationship in modelbuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
    {
        relationship.DeleteBehavior = DeleteBehavior.Restrict;
    }

    base.OnModelCreating(modelbuilder);
}

Ответ 2

Конструкция

modelBuilder.Entity("myNamespace.Models.ChangeOrder", b =>
    {
        b.HasOne("myNamespace.Models.User")
            .WithMany()
            .HasForeignKey("CreatedByID")
            .OnDelete(DeleteBehavior.Cascade);
    });

означает создание FK_ChangeOrder_User_CreatedByID с помощью REFERENCES [dbo].[User] ([CreatedByID]) ON DELETE CASCADE. Он должен существовать в protected override void BuildModel(ModelBuilder modelBuilder) of YourContextModelSnapshot.cs, созданный во время миграции. Я не уверен, что полностью понимаю ваш вопрос, но я думаю, что вы должны либо добавить такую ​​конструкцию в XXXModelSnapshot.cs, либо удалить ненужную конструкцию, которая уже существует здесь.

ОБНОВЛЕНО: Я вижу, что у вас есть проблема в модели. У вас есть следующие свойства в

public Int16? ApprovedByID { get; set; }
public Int16 AssignedToID { get; set; }
public Int16 CreatedByID { get; set; }

// navigation properties

[ForeignKey("ApprovedByID")]
public User ApprovedBy { get; set; }

[ForeignKey("AssignedToID")]
public User AssignedTo { get; set; }

[ForeignKey("CreatedByID")]
public User CreatedBy { get; set; }

По умолчанию миграция попытается установить DeleteBehavior.Cascade для всех свойств.

Вы можете перезаписать поведение, изменив OnModelCreating, который устанавливает либо поведение DeleteBehavior.Restrict для всех ключей, либо устанавливает только одну клавишу в поведении DeleteBehavior.Cascade или DeleteBehavior.SetNull. Например, в приведенном ниже коде используется DeleteBehavior.Cascade на CreatedByID (который создает внешние ключи ON DELETE CASCADE) и DeleteBehavior.Restrict для других внешних ключей (нет ON DELETE для внешних ключей):

public class JobSightDBContext : DbContext
{
    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        base.OnModelCreating(modelbuilder);

        modelbuilder.Entity(typeof (ChangeOrder))
            .HasOne(typeof (User), "ApprovedBy")
            .WithMany()
            .HasForeignKey("ApprovedByID")
            .OnDelete(DeleteBehavior.Restrict); // no ON DELETE
        modelbuilder.Entity(typeof (ChangeOrder))
            .HasOne(typeof (User), "AssignedTo")
            .WithMany()
            .HasForeignKey("AssignedToID")
            .OnDelete(DeleteBehavior.Restrict); // no ON DELETE
        modelbuilder.Entity(typeof (ChangeOrder))
            .HasOne(typeof (User), "CreatedBy")
            .WithMany()
            .HasForeignKey("CreatedByID")
            .OnDelete(DeleteBehavior.Cascade); // set ON DELETE CASCADE
    }

    DbSet<ChangeApprovalStatus> ChangeApprovalStatus { get; set; }
    DbSet<ChangeImpact> ChangeImapct { get; set; }
    DbSet<ChangeOrder> ChangeOrders { get; set; }
    DbSet<ChangePriority> ChangePriorities { get; set; }
    DbSet<ChangeStatus> ChangeStatus { get; set; }
    DbSet<ChangeType> ChangeTypes { get; set; }
    DbSet<User> Users { get; set; }
}