2013-06-06 12 views
11

È possibile creare un'associazione unidirezionale molti a molti nell'entità framework 6 con codice prima e annotazioni? Esempio:Entity framework 6 code first - one way many to many via annotazioni

class Currency 
{ 
    public int id { get; set; } 
} 

class Country 
{ 
    public int id { get; set; } 

    // How i can annotate this property to say EF that it is many-to-many 
    // and it should create mapping table? 
    // I don't need navigation property to Country in Currency class! 
    public virtual IList<Currency> currencies { get; set; } 
} 

Su annotazioni Java + JPA posso realizzare quello che mi serve in questo modo:

@OneToMany 
@JoinTable(name = "MAPPING_TABLE", joinColumns = { 
    @JoinColumn(name = "THIS_ID", referencedColumnName = "ID") 
}, inverseJoinColumns = { 
    @JoinColumn(name = "OTHER_ID", referencedColumnName = "ID") 
}) 

affermativo, EF hanno caratteristiche uguali?

risposta

0

Penso che tu voglia imparare come separare le relazioni dalle prime entità del codice EF. Ho iniziato un argomento su here su questa domanda. Voglio separare gli oggetti di relazione dall'entità e ho usato le classi parziali. Nella mia domanda voglio imparare come separare le classi parziali per classe bilrary. Ma non poteva.

Mentre stavo usando NHibernate, stavo usando la mappatura XML e creando relazioni qui, nella piattaforma java è la stessa cosa. Ma penso che Entity Framework non sia ancora pronto.

30

È possibile farlo specificando esplicitamente la relazione utilizzando l'API Fluent. Override del metodo della classe DbContextOnModelCreating(), e nella tua esclusione specificare i dettagli della tabella di mapping in questo modo:

class MyContext : DbContext 
{ 
    public DbSet<Currency> Currencies { get; set; } 
    public DbSet<Country> Countries { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Country>() 
      .HasMany(c => c.Currencies) 
      .WithMany()     // Note the empty WithMany() 
      .Map(x => 
      { 
       x.MapLeftKey("CountryId"); 
       x.MapRightKey("CurrencyId"); 
       x.ToTable("CountryCurrencyMapping"); 
      }); 

     base.OnModelCreating(modelBuilder); 
    } 
} 

Si noti che - nel mio test rapido in ogni caso - si dovrà Include() la proprietà Valute durante il caricamento del oggetto EF per avere la lista popolato:

  var us = db.Countries 
         .Where(x => x.Name == "United States") 
         .Include(x=>x.Currencies) 
         .First(); 

EDIT

Se davvero si vuole fare tutto con dati annotazioni, e non utilizzare Fluent a tutti, allora è possibile modellare la j oin table esplicitamente come indicato elsewhere. Ci sono diversi svantaggi di usabilità di questo approccio, tuttavia, sembra che il metodo Fluent sia l'approccio migliore.

class Country 
{ 
    public int Id { get; set; } 
    public virtual ICollection<CountryCurrency> CountryCurrencies { get; set; } 
} 

class Currency 
{ 
    public int Id { get; set; } 
} 

class CountryCurrency 
{ 
    [Key, Column(Order=0)] 
    public virtual int CountryId { get; set; } 
    [Key, Column(Order=1)] 
    public virtual int CurrencyId { get; set; } 

    public virtual Country Country { get; set; } 
    public virtual Currency Currency { get; set; } 
} 
+0

Grazie ... È possibile eseguire questa configurazione solo con le annotazioni? – Anton

+0

Penso che la cosa migliore da fare sarebbe quella di modellare esplicitamente la tabella di join. Quindi, crea una classe CountryCurrency insieme agli altri oggetti EF e sostituisci la proprietà 'valute' nell'oggetto Paese con un' ICollection '. Ciò tuttavia ha degli svantaggi di usabilità, poiché EF non eseguirà automaticamente le JOINS dietro le quinte per te. –

+0

Strano che non ci sia modo di farlo con gli attributi. EF è un casino. – yonexbat

0

Si può fare questo nel codice prima abbastanza facilmente in EF 6.

public class Country 
{ 
    public int ID {get;set;} 

    public virtual ICollection<Currency> Currencys {get;set;}//don't worry about the name,  pluralisation etc 


} 

public class Currency 
{ 

    public int ID {get;set;} 

    public virtual ICollection<Country> Countrys {get;set;}//same as above - 

} 

compilarlo, eseguirlo e oplà - la magia si uniscono tavolo in background. Dipende se le convenzioni di denominazione ti danno fastidio. Personalmente penso che se stai facendo il codice prima, dovresti fare tutto nel codice. Alcune persone preferiscono l'annotazione, alcuni preferiscono l'API fluente - usa quello che preferisci.

+0

La domanda era esplicita su una navigazione a senso unico. L'aggiunta di Paesi alla Valuta rimuove questa restrizione. – KyorCode

+0

Ho sentito quello che stai dicendo, ma da quello che posso dire, le proprietà di navigazione a 1 modo sono quelle che vanno contro i primi principi del codice. Qual è lo svantaggio di inserire entrambe le collezioni? Diventa meno performante? – Will