【问题标题】:How to configure many to many relationship using entity framework fluent API如何使用实体框架流式 API 配置多对多关系
【发布时间】:2012-02-14 04:25:26
【问题描述】:

我首先尝试在 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

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

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

【问题讨论】:

  • 这不是你想要的多对多吗?
  • 谢谢 - 编辑标题以反映正确的含义
  • 格式正确的问题。容易理解。

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


【解决方案1】:
modelBuilder.Entity<Account>()
            .HasMany(a => a.Products)
            .WithMany()
            .Map(x =>
            {
                x.MapLeftKey("Account_Id");
                x.MapRightKey("Product_Id");
                x.ToTable("AccountProducts");
            });

【讨论】:

  • 感谢 - 将其标记为已接受的答案,因为这允许我设置单向关联,而无需在 Product 类中添加(不需要的)关联
  • 如果我想关注相关表上的其他数据,如添加日期、关系类型等,我可以为 AccountProducts 定义 POCO 吗?在这种情况下,您将如何进行映射?
  • 这对我有用,但只有在我在.WithMany() 中添加了等效的p =&gt; p.Accounts 之后。如果不这样做,它会在 Accounts 中创建一个奇怪的属性。
  • 我不确定这是否是预期的行为——但就我而言,我的 public virtual ICollection&lt;Product&gt; Products { get; set; } 正在删除重复项。因此,如果有 2 行 (Account_ID, Product_ID)(1, 1),我的 Products collection.ToList() 仅包含一条 id 为 1 的记录
  • @Chris 如果没有那个随机评论,而我随机阅读它,我会被卡住的。谢谢!
【解决方案2】:

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

【讨论】:

  • 哦,这很简单——但是为什么我们需要在这里进行双向关联呢?在域模型中,我们不想通过每个产品访问帐户。
  • 如果一个产品不知道它附加到哪个帐户,则无法定义关系。例如,如果您使用 viewModel,您始终可以排除 accountId 并仅映射您需要的数据
  • 你知道任何隐藏(访问修饰符?)双向关联的方法吗?
  • 见我上面的评论。在您的 viewModel 或 DTO 对象或您正在使用的任何东西中,从映射中排除 AccountId,这将对使用您的类的任何人隐藏。如果你想从数据库中删除它,那是做不到的。数据库需要有这个列来定义关系
  • @NinjaNye 如果我需要为加入表定义一个单独的键该怎么办?
【解决方案3】:

代码优先是以正确的关系方式创建表。当

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

Products 表应该存储其帐户的密钥,就像现在一样。

您试图在 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; }
}

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

【讨论】:

    【解决方案4】:
            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"));
        }
    

    【讨论】:

      猜你喜欢
      • 2017-01-28
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多