2016-01-13 11 views
16

W Entity Framework 7, gdy próbuję zastosować migracji pojawia się błądOkreślanie ON DELETE NO ACTION w Entity Framework 7?

Wprowadzenie ograniczenia klucz obcy „FK_ChangeOrder_User_CreatedByID” na stole „ChangeOrder” może powodować cykli lub wiele ścieżek kaskadowe. Określ ON DELETE NO ACTION lub ON UPDATE NO ACTION lub zmodyfikuj inne ograniczenia klucza OBCEGO.
Nie można utworzyć ograniczenia. Zobacz poprzednie błędy.

wiem w starszych wersjach Entity Framework byś sobie z tym poradzić, dodając

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

do DbContext ale w EF7 modelBuilder nie wydaje się mieć .Conventions do niego i google zwraca tylko starsze EF 4 mimo EF 6 wyników.

Jak konkretnie ograniczyć ograniczenie ON DELETE NO ACTION w Entity Framework 7?

Edytuj: Odpowiedź udzielona przez Olega będzie widoczna dla każdego klucza obcego, ale chciałbym zrobić to globalnie, ponieważ znacznie łatwiej będzie użyć jednego wiersza kodu, aby zadeklarować to globalnie, a następnie określić kod dla każdy z setek relacji, które będę miał.

Edycja 2: Kod Oleg

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; } 
} 

Odpowiedz

25

Po kopania wokół na GitHut i pracy z bardzo patent facet z SM na GitHub obecne rozwiązanie jest dodanie tego do 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); 
} 
+0

to uratowało mi życie !!!!! Otrzymywałem wiele modelujących problemów FK. Stukrotne dzięki!!!!!!!!!!!!!! –

10

Konstrukcja

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

będzie to tworzenie FK_ChangeOrder_User_CreatedByID z REFERENCES [dbo].[User] ([CreatedByID]) ON DELETE CASCADE. Powinien istnieć w protected override void BuildModel(ModelBuilder modelBuilder) z YourContextModelSnapshot.cs utworzony podczas migracji. Nie jestem pewien, czy w pełni rozumiem twoje pytanie, ale myślę, że powinieneś dodać taki konstrukt do XXXModelSnapshot.cs lub usunąć niepotrzebny konstrukt, który już istnieje tutaj.

ZAKTUALIZACJA: Widzę, że masz problem w Modelu. Dostępne są następujące właściwości w

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; } 

domyślnie migracji spróbuj ustawić DeleteBehavior.Cascade na wszystkich właściwości.

Można nadpisać zachowanie zmieniając OnModelCreating, który określa zarówno DeleteBehavior.Restrict zachowanie dla wszystkich klawiszy lub ustawić na jednym jedynym kluczem zachowanie DeleteBehavior.Cascade lub DeleteBehavior.SetNull. Na przykład, poniższy kod wykorzystuje DeleteBehavior.Cascade na CreatedByID (który tworzy ON DELETE CASCADE na kluczy obcych) oraz DeleteBehavior.Restrict na innych kluczy obcych (nie ON DELETE na klucze obce):

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; } 
} 
+0

Czy istnieje sposób, aby to zrobić globalnie czy też muszę to zrobić dla każdego z setek relacji mam?Zrobienie tego w ten sposób stworzy dla mnie dużo dodatkowego kodowania i wolałbym tego uniknąć. – Matthew

+0

@MatthewVerstraete: Trudno jest odpowiedzieć, mając tylko komunikat o błędzie. Przypuszczam, że najpierw stworzyłeś zestaw klas, które mają wiele notacji danych, a następnie utworzyłeś 'XXXContext' wyprowadzony z' DbContext', który ma wiele właściwości, takich jak 'public DbSet Users {get; zestaw; } ',' public DbSet ChangeOrders {get; zestaw; } '. Przypuszczam, że niektóre definicje w 'User',' ChangeOrder' będą interpretowane w niewłaściwy sposób przez Migracje EF, ale nie mogę zgadnąć, co to dokładnie może być. Jedną z nich jest analiza pełnego modelu, aby znaleźć przyczynę. – Oleg

+0

Nie wiesz, jakie masz problemy ze zrozumieniem. Szukam wersji EF7 'modelBuilder.Conventions.Remove ();' ale dodałem DBContext i model, aby spojrzeć na – Matthew

Powiązane problemy