2013-05-10 8 views
5

Ich habe eins zu eins Beziehung mit Fremdschlüsseln, aber die Cascade Delete ist aus irgendeinem Grund nicht aktiviert. Der Beispielcode ist unten.Code erste eins zu eins aktivieren Kaskade löschen

public class AppRegistration 
{ 
    public int AppRegistrationId { get; set; } 
    [Required] 
    [StringLength(50)] 
    [Display(Name = "Username")] 
    public string UserName { get; set; } 
    [Required] 
    [StringLength(100)] 
    public string Password { get; set; } 
    [StringLength(20)] 
    public string StudentOrAgent { get; set; } 
    // navigation properties 
    public virtual AppStatus AppStatus { get; set; } 
    public virtual Agreement Agreement { get; set; } 
    public virtual AnotherTable AnotherTable { get; set; } 
} 

Die abhängige Tabelle mit einem Fremdschlüssel ist unten.

public class Agreement 
{ 
    [Key] 
    [ForeignKey("AppRegistration")] 
    public int AppRegistrationId { get; set; } 
    public DateTime DateAgreed { get; set; } 
    public virtual AppRegistration AppRegistration { get; set; } 
} 

Wenn ich versuche, einen Eintrag aus der generierten AppRegistrations Tabelle zu löschen, erhalte ich eine Referenz Einschränkung Konflikt.

Ich habe versucht, [Required] auf die Navigationseigenschaft in der abhängigen Tabelle, aber es tut nichts - der Update-Database Befehl zeigt die No pending code-based migrations. Nachricht. Irgendwelche Ideen? Vielen Dank.

Update: ich die folgende Fehlermeldung erhalten:

The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.AppStatus_dbo.AppRegistrations_AppRegistrationId". The conflict occurred in database "MVCapp", table "dbo.AppStatus", column 'AppRegistrationId'.

Antwort

8

ich das cascade delete Problem in einem separaten Beispielprojekt zu erarbeiten entschieden. Ich fand den folgenden Blog & MSDN-Seiten sehr nützlich.

Mit dem Code First Ansatz die folgenden Modell zu erstellen.

public class Category 
{ 
    public int CategoryId { get; set; } 
    public string CategoryName { get; set; } 
    public virtual Book Book { get; set; } 
} 
public class Book 
{ 
    public int CategoryId { get; set; } 
    public string BookTitle { get; set; } 
    public string BookAuthor { get; set; } 
    public string BookISBN { get; set; } 
    public virtual Category Category { get; set; } 
} 

(Ich weiß, die Entitätsnamen einer Eins-zu-viele-Beziehung vorschlagen, aber ich versuche, 1-zu-1-Beziehung zu modellieren, wie es in meiner ursprünglichen Frage an der Spitze.)

So, im obigen Modell kann jede Kategorie nur eine haben Buch.

Fügen Sie in Ihrer DbContext-abgeleiteten Klasse Folgendes hinzu.

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 

    modelBuilder.Entity<Book>() 
     .HasKey(t => t.CategoryId); 

    modelBuilder.Entity<Category>() 
     .HasRequired(t => t.Book) 
     .WithRequiredPrincipal(t => t.Category) 
     .WillCascadeOnDelete(true); 
} 

(Die folgenden Namensräume sind für den obigen Code erforderlich: System.Data.Entity, System.Data.Entity.ModelConfiguration.Conventions.)

Dies schafft richtig die 1-zu-1-Beziehung.Sie haben einen Primärschlüssel in jeder Tabelle und einen Fremdschlüssel in Book Tabelle mit ON DELETE CASCADE aktiviert.

Database Diagram for the model

In dem obigen Code auf der Category Einheit I WithRequiredPrincipal()mitt => t.Category Argumente verwendet wird, wobei das Argument die Fremdschlüsselspalte in der abhängigen Tabelle ist.

Wenn Sie WithRequiredPrincipal()ohne ein Argument verwenden werden Sie eine zusätzliche Spalte in der Tabelle Book erhalten und Sie werden zwei Fremdschlüssel in der Book Tabelle zeigt auf CategoryId in Category Tisch.

Ich hoffe, dass diese Info hilft.

http://msdn.microsoft.com/en-us/data/jj591620#RequiredToRequired

5

Ein Grund, warum Sie nicht Cascading löschen bekommen ist, weil Ihre Beziehung ist optional.

Wenn Sie die Beziehung also ein AppRegistration erforderlich wollen muss man Agreement haben Sie verwenden können (Cascading löschen automatisch konfiguriert):

public class Agreement 
{ 
    ... 
    [Required] 
    public AppRegistration AppRegistration{ get; set; } 
} 

Wenn Sie die Beziehung wollen optional sein mit Cascading löschen Sie diese konfigurieren können mit Fluent API:

modelBuilder.Entity<AppRegistration>() 
    .HasOptional(a => a.Agreement) 
    .WithOptionalDependent() 
    .WillCascadeOnDelete(true); 
+0

Danke für die Antwort:

UPDATE

Später ich Antwort direkt hier. Ich habe versucht, '[Required]' zu setzen, aber die 'Update-Database' der Code-Migration gibt 'No anstehende code-basierte Migrationen' zurück. Irgendeine Möglichkeit, dies zu umgehen? – erdinger

+1

Ich könnte falsch liegen, aber ich denke, Sie würden nicht die erste Technik versuchen wollen, weil es fast unmöglich ist, eine Eins-zu-Eins-Beziehung zu erfüllen, die in beiden Richtungen erforderlich ist. Wenn Sie versuchen, die Vereinbarung einzufügen, erhalten Sie eine Constraint-Verletzung, weil AppRegistration nicht existiert und umgekehrt. – AaronLS

+0

@ user2291748 Haben Sie vor dem Ausführen von update-database eine Migration hinzugefügt? Aaron, vielleicht hast du Recht, es ist nur etwas, das mir in den Sinn kam. – MattSull

Verwandte Themen