2012-01-19 14 views
23

Sto provando a impostare una relazione molti a molti prima nel codice EF, ma le convenzioni di default si sbagliano. Le seguenti classi descrive la relazione:Come configurare una relazione molti a molti usando l'API fluidica dell'entità 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; } 
} 

Un account può avere molti prodotti.

Tuttavia le convenzioni EF creeranno le tabelle DB come:

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

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

questo non sembra come una relazione molti-a-molti struttura della tabella? Come posso ottenere configurare l'API fluente in modo da riflettere il rapporto e creare una tabella intermedia:

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

non è quella che si desidera una relazione molti a molti? –

+0

Grazie - Modifica il titolo per riflettere sul significato corretto – Fixer

+1

Domanda ben formattata. Facile da capire. –

risposta

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

Grazie per questo: contrassegnerà questa come risposta accettata in quanto ciò mi consente di impostare un'associazione unidirezionale senza dover aggiungere un'associazione (non necessaria) nella classe Product – Fixer

+0

Cosa fare se desidero seguire ulteriori dati nella tabella di correlazione , come date_added, tipo di relazione ecc. Posso definire un POCO per AccountProducts? E come faresti la mappatura in questo caso? – hazimdikenli

+0

@hazimdikenli: non è possibile utilizzare una relazione molti-a-molti. È necessario modellarlo con due relazioni uno-a-molti. I dettagli sono qui: http://stackoverflow.com/questions/7050404/create-code-first-many-to-many-with-additional-fields-in-association-table/7053393#7053393 – Slauma

6

Cosa EF ha suggerito una relazione uno-a-molti.

Un account può avere molti prodotti, cioè ogni prodotto ha un'ACCOUNT_ID

Se si desidera una relazione molti a molti (e di creare una tabella intermedia), il seguente dovrebbe funzionare

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, è stato facile - Ma perché abbiamo bisogno di un'associazione bidirezionale qui? Nel modello di dominio non vogliamo accedere agli account tramite ciascun prodotto. – Fixer

+0

Se un prodotto non sa a quale account è collegato, non c'è modo di definire la relazione. Se si utilizza viewModels, ad esempio, è sempre possibile escludere l'accountId e mappare solo i dati necessari – NinjaNye

+0

Conosci un modo per nascondere (modificatore di accesso?) L'associazione bidirezionale? – Fixer

1

Codice primo sta creando tabelle in modo relazionale giusto. Quando

Un account può avere molti prodotti.

La tabella dei prodotti deve memorizzare la chiave per il proprio account, come in effetti avviene ora.

Quello che stai cercando di vedere in db, è una relazione molti-a-molti, non uno a molti. Se si vuole raggiungere che con il codice di prima, si dovrebbe ridisegnare i tuoi entità

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

In questo caso, un prodotto può avere molti conti, e un account può avere molti prodotti.

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