2012-01-19 20 views
23

Estoy tratando de establecer una relación de muchos a muchos en el código EF primero, pero las convenciones predeterminadas es equivocarse. Las siguientes clases describe la relación:Cómo configurar una relación de muchos a muchos utilizando el marco de la entidad con fluidez API

class Product 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

class Account 
{   
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Product> Products { get; set; } 
} 

Una cuenta puede tener muchos productos.

Sin embargo las convenciones EF crearán las tablas de datos como:

Products Table 
-------------- 
Id 
Name 
Account_Id <- What is this? 

Accounts Table 
-------------- 
Id 
Name 

Esto no se ve como una estructura de tabla de muchos a muchos? ¿Cómo puedo conseguir configurar el API fluida para reflejar la relación y crear una tabla de intermediario:

AccountProducts Table 
--------------------- 
Account_Id 
Product_Id 
+1

no es la que desea que un muchos a muchos? –

+0

Gracias - Edite el título para reflejarlo y corregir el significado – Fixer

+1

Pregunta bien formateada. Fácil de comprender. –

Respuesta

53
modelBuilder.Entity<Account>() 
      .HasMany(a => a.Products) 
      .WithMany() 
      .Map(x => 
      { 
       x.MapLeftKey("Account_Id"); 
       x.MapRightKey("Product_Id"); 
       x.ToTable("AccountProducts"); 
      }); 
+0

Gracias por esto: marcará esto como la respuesta aceptada, ya que esto me permite configurar una asociación unidireccional sin la necesidad de agregar una asociación (innecesaria) en la clase de producto – Fixer

+0

¿Qué ocurre si deseo seguir datos adicionales en la tabla de correlación? , como date_added, tipo de relación, etc. ¿Puedo definir un POCO para AccountProducts? ¿Y cómo harías el mapeo en este caso? – hazimdikenli

+0

@hazimdikenli: Entonces no puedes usar una relación de muchos a muchos. Debe modelar esto con dos relaciones uno a muchos. Los detalles están aquí: http://stackoverflow.com/questions/7050404/create-code-first-many-to-many-with-additional-fields-in-association-table/7053393#7053393 – Slauma

6

Lo EF ha sugerido es una relación de uno a muchos.

Una cuenta puede tener muchos productos, es decir, cada producto tiene un Account_ID

Si desea una relación muchos a muchos (y crear una tabla de intermediario), el siguiente debería funcionar Código

class Product 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Account> Accounts { get; set; } 
} 

class Account 
{   
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Product> Products { get; set; } 
} 
+0

Oh, eso fue fácil - Pero ¿por qué necesitamos una asociación bidireccional aquí? En el modelo de dominio, no queremos acceder a las cuentas a través de cada producto. – Fixer

+0

Si un producto no sabe a qué cuenta está conectado, no hay forma de definir la relación. Si usa viewModels, por ejemplo, siempre puede excluir el accountId y solo mapear los datos que necesita – NinjaNye

+0

¿Conoce alguna forma de ocultar (modificador de acceso) la asociación bidireccional? – Fixer

1

primera está creando tablas en la forma relacional correcta. Cuando

Una cuenta puede tener muchos productos.

La tabla de productos debe almacenar la clave para su cuenta, como lo hace ahora.

Lo que está tratando de ver en db, es la relación muchos a muchos, no uno a muchos. Si se quiere lograr que, con código en primer lugar, usted debe rediseñar sus entidades

class Product 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Account> Accounts { get; set; } 
} 

class Account 
{   
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Product> Products { get; set; } 
} 

En este caso, un producto puede tener muchas cuentas, y una cuenta puede tener muchos productos.

1
 public AccountProductsMap() 
    { 
     this.ToTable("AccountProducts"); 
     this.HasKey(cr => cr.Id); 

     this.HasMany(cr => cr.Account) 
      .WithMany(c => c.Products) 
      .Map(m => m.ToTable("AccountProducts_Mapping")); 
    } 
Cuestiones relacionadas