9

Estoy comenzando a usar el código EF First con MVC y estoy un poco perplejo con algo. Tengo la siguiente estructura db (Lo siento, pero no se le permitió publicar una imagen por desgracia):Código EF Primero con muchas referencias autorreferenciales

de mesa - Productos
de mesa - RelatedProducts

1-Muchos en Products.ProductID -> RelatedProducts.ProductID
1-Muchos en Products.ProductIDID> Related Products. Related Product ID

Básicamente tengo un producto que puede tener una serie de productos que están relacionados con él. Estos se guardan en la tabla Related Products con la relación definida por el ProductID y el ProductID del producto relacionado que he denominado RelatedProductID. En mi código que ha producido las siguientes clases:

public class MyDBEntities : DbContext 
{ 
    public DbSet<Product> Products { get; set; } 
    public DbSet<RelatedProduct> RelatedProducts { get; set; } 
} 

public class Product 
{ 
    public Guid ProductID { get; set; } 
    public string Name { get; set; } 
    public string Heading { get; set; } 
    public string Description { get; set; } 
    public decimal Price { get; set; } 
    public Guid CategoryID { get; set; } 
    public string ImageURL { get; set; } 
    public string LargeImageURL { get; set; } 
    public string Serves { get; set; } 
    public virtual List<RelatedProduct> RelatedProducts { get; set; } 
} 
public class RelatedProduct 
{ 
    public Guid ProductID { get; set; } 
    public Guid RelatedProductID { get; set; } 
    public virtual Product Product { get; set; } 
    public virtual Product SimilarProduct { get; set; } 
} 

entonces trato de acceder a estos en código usando:

myDB.Products.Include("RelatedProducts").Where(x => x.ProductID == productID).FirstOrDefault(); 

pero aparece el siguiente error:

{"Invalid column name 'ProductProductID2'.\r\nInvalid column name 'ProductProductID2'.\r\nInvalid column name 'ProductProductID'.\r\nInvalid column name 'ProductProductID1'.\r\nInvalid column name 'ProductProductID2'."} 

Lo estoy haciendo mal? Básicamente quiero obtener un producto, luego recorrer los Productos relacionados y mostrar esa información del producto.

Respuesta

9

La primera parte de la respuesta es que EF4 CTP5 no correlaciona correctamente sus POCO con la base de datos porque no es lo suficientemente inteligente. Si consulta la base de datos, obtendrá:

CREATE TABLE RelatedProducts(
     RelatedProductID uniqueidentifier NOT NULL, 
     ProductID uniqueidentifier NOT NULL, 
     ProductProductID uniqueidentifier NULL, 
     ProductProductID1 uniqueidentifier NULL, 
     ProductProductID2 uniqueidentifier NULL, 
     PRIMARY KEY CLUSTERED 
     (
      RelatedProductID ASC 
     ) 
    ) ON [PRIMARY] 

¡Yuck! Esto necesita ser arreglado con un poco de trabajo manual. En su DbContext, se agrega reglas de este modo:

protected override void OnModelCreating(ModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Product>() 
      .Property(p => p.ProductID) 
      .HasDatabaseGenerationOption(DatabaseGenerationOption.Identity); 

     modelBuilder.Entity<RelatedProduct>() 
      .HasKey(rp => new { rp.ProductID, rp.RelatedProductID }); 

     modelBuilder.Entity<Product>() 
      .HasMany(p => p.RelatedProducts) 
      .WithRequired(rp => rp.Product) 
      .HasForeignKey(rp => rp.ProductID) 
      .WillCascadeOnDelete(); 

     modelBuilder.Entity<RelatedProduct>() 
      .HasRequired(rp => rp.SimilarProduct) 
      .WithMany() 
      .HasForeignKey(rp=> rp.RelatedProductID) 
      .WillCascadeOnDelete(false); 

     base.OnModelCreating(modelBuilder); 
    } 
+0

tener cuidado de observar que no podemos eliminar la cascada sobre la relación entre Producto.IDProducto y RelatedProduct.RelatedProductID. Esto no es una limitación de EF4: es necesario para evitar eliminaciones en cascada cíclicas. – anon

+0

También tenga en cuenta que las relaciones no son simétricas. Si se agrega product1 en relación con product2, product2 no se relaciona automáticamente con product1. – anon

+0

Excelente, funcionó perfectamente, gracias por eso, ¡he intentado hacer esto por años! – knappster

Cuestiones relacionadas