2011-04-03 33 views
35

Estoy diseñando mi base de datos usando código primero y necesito un poco de ayuda, creo.Entity Framework Code First - Definición de relaciones/claves

estoy recibiendo este error:

Introducing FOREIGN KEY constraint 'SalesOrder_Invoices' on table 'Invoices' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.

Estoy tratando de tener las relaciones/teclas siguientes:

--> = 1 to Many Relationship 
  1. Clientes -> CustomerLocation
  2. CustomerLocation -> SalesOrder
  3. SalesOrder -> Factura
  4. SalesRep -> SalesOrder
  5. PaymentTerm -> Cliente
  6. PaymentTerm -> SalesOrder
  7. PaymentTerm -> Factura

Estoy tratando de definirlos por el estándar de:

<ClassName><PrimaryKeyID> 

Ejemplo: Customer tiene ID propiedad, por lo que en CustomerLocation i definir la clave externa de este modo:

Public Property CustomerID AS Integer 

Todo lo que tengo que hacer es definir la clave externa correcta? ¿También tengo que tener propiedades de navegación para cada tecla que defina?

Y, ¿no puedo tener varias claves foráneas en la misma clave principal de un objeto?

Actualizado

Así que para definir una relación, no se utiliza el ClassName.PrimaryKeyProperty? o usas propiedades de navegación? ¿O ambos? ¡¡Confuso!!

Actualización 2

Así que para que una relación funcione tiene que definir ambos lados ... creo.

Public Class Customer 
    Public Property ID AS Integer 
    Public Overrideable Property Locations AS ICollection(OF CustomerLocation) 

End Class 

Public Class CustomerLocation 
    Public Property ID AS Integer 
    Public Property CustomerID AS Integer 

End Class 

Respuesta

95

Esta es una excepción causada por el servidor SQL cuando tiene varias rutas de eliminaciones en cascada. Si elimina su PaymentTerm, activará la eliminación en cascada en las tres relaciones. Esto explotará al crear SalesOrder o Invoice.EF crea por defecto todos los muchos uno a las relaciones con ON DELETE CASCADE puede volver a asignar su relación específica con lo use por:

modelBuilder.Entity<...>() 
      .HasRequired(...) 
      .WithMany(...) 
      .HasForeignKey(...) 
      .WillCascadeOnDelete(false); 

O puede apagarlo globaly mediante la eliminación de la convención:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

Usted puede conseguir alrededor de este error en una migración particular, mediante la modificación del método generado Up() con una línea como la siguiente:

AddForeignKey("dbo.Payments", "EventID", "dbo.Events", "EventID", cascadeDelete: true) 

y cambiar º en cascadeDelete: valor a falso en la (s) relación (es) ofensiva (s).

+0

Entonces, para que una relación funcione, ¿tiene que definir ambos lados? Por favor, mira mi actualización anterior. – Sam

+0

@Sam: No, no necesita propiedad de navegación en ambos lados. –

+13

Me encanta esta respuesta para la sugerencia 'OneToManyCascadeDeleteConvention'. – batwad

4

Leer this, estoy seguro de que esto ayudará a encontrar la respuesta.

Además, según ScottGu de blogpost, creo que, en general, debe ser que acaba de crear las clases de la siguiente manera (que no he leído con cuidado lo suficiente, por lo que debe comprobar que funciona para más detalles):

public class Customer 
{ 
    public int CustomerID { get; set; } 
    public int CustomerLocationID { get; set; } 
    public virtual CustomerLocation Location { get; set; } 
} 

public class CustomerLocation 
{ 
    public int CustomerLocationID { get; set; } 
    public virtual ICollection<Customer> Customers { get; set; } 
} 
Cuestiones relacionadas