如何使用实体框架流畅的API配置多对多关系

时间:2012-01-19 13:58:05

标签: c# entity-framework-4.1 ef-code-first associations

我正在尝试首先在EF代码中设置多对多关系,但默认约定是错误的。以下类描述了这种关系:

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

一个帐户可以包含多个产品。

但是,EF约定会将DB表创建为:

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

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

这看起来不像是多对多的表结构?如何配置流畅的API以反映关系并创建中间表:

AccountProducts Table
---------------------
Account_Id
Product_Id

4 个答案:

答案 0 :(得分:58)

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

答案 1 :(得分:7)

EF所建议的是一对多的关系。

一个帐户可以有多个产品,即每个产品都有一个Account_Id

如果您想要多对多关系(并创建一个中间表),以下内容应该可以正常工作

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

答案 2 :(得分:2)

代码首先是以正确的关系方式创建表。什么时候

  

一个帐户可以有很多产品。

产品表应该存储其帐户的密钥,就像它现在实际上一样。

您在db中尝试看到的是多对多关系,而不是一对多关系。如果您想首先使用代码实现该功能,则应重新设计实体

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

在这种情况下,一个产品可以拥有多个帐户,一个帐户可以拥有多个产品。

答案 3 :(得分: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"));
    }