Entity framework 6 code first - один путь от многих до многих через аннотации

Можно ли создать одностороннюю ассоциацию "многие ко многим" в инфраструктуре сущности 6 с первым кодом и аннотациями? Пример:

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

В аннотациях Java + JPA я могу реализовать то, что мне нужно:

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

Итак, имеет ли EF равные функции?

Ответ 1

Вы можете сделать это, указав связь явно с использованием Fluent API. Переопределите метод OnModelCreating() вашего класса DbContext, а в вашем переопределении укажите данные таблицы сопоставления следующим образом:

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

Обратите внимание, что в любом случае в моем быстром тесте вам нужно будет Include() свойство Currencies при загрузке объекта EF для заполнения списка:

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

ИЗМЕНИТЬ

Если вы действительно хотите сделать все с помощью Data Annotations, а не использовать Fluent вообще, то вы можете моделировать таблицу соединений явно, как указано в другом месте. Однако существуют различные недостатки использования этого подхода, поэтому, по-видимому, наилучшим подходом является метод Fluent.

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

Ответ 2

Я думаю, вы хотите узнать, как отделить отношения от первых объектов EF-кода. Я начал тему в здесь об этом вопросе. Я хочу отделить объекты отношения от сущности, и я использовал частичные классы. В моем вопросе я хочу узнать, как отделить частичные классы по классу. Но не мог.

Пока я использовал NHibernate, я использовал XML-сопоставление и создавал отношения здесь. В java-платформе это то же самое. Но я думаю, что Entity Framework еще не готова.

Ответ 3

Вы можете сделать это в коде вначале довольно легко в 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 - 

}

Скомпилируйте его, запустите его, и hey presto - magic join table в фоновом режиме. Зависит от того, Я лично думаю, что если вы делаете код первым, вы должны сделать все это в коде. Некоторые люди предпочитают аннотацию, некоторые предпочитают свободный API - используйте то, что вы предпочитаете.