Entity Framework 中相同 class 的多个列表

Multiple lists of same class in Entity Framework

我试图首先在 Entity Framework 代码中创建与相同类型有关系的公司的数据模型。我想创建单向关系,因此当一家公司将另一家公司添加为客户时,另一家公司不会自动将该公司作为供应商。

public class Company {
    [Key]
    public string Id { set; get; }
    public string Name { set; get; }

    public virtual ICollection<Company> Customers { set; get; }
    public virtual ICollection<Company> Suppliers { set; get; }
}

当我像这样更新数据库时,我最终得到一个名为 "CompanyCompanies" 的连接 table。

公司公司

| Company_Id | Company_Id1 |
|------------|-------------|
| 1234       | 1234        |

我想创建两个 table 来连接这些值,如下所示:

公司客户

| Company_Id | Customer_Id |
|------------|-------------|
| 1234       | 1234        |

公司供应商

| Company_Id | Supplier_Id |
|------------|-------------|
| 1234       | 1234        |

我看了很多流利的 api 并试图定义那里的关系,但我似乎无法理解如何做到这一点。我发现了很多使用不同实体的示例,但只有 this answer 与自身有关系。但是,当我实施该问题的解决方案并更新数据库时,出现连接超时错误。

modelBuilder.Entity<Company>()
    .HasMany(c => c.Customers)
    .WithMany()
    .Map(m =>
    {
        m.ToTable("CompanyCustomer");
        m.MapLeftKey("CompanyId");
        m.MapRightKey("CustomerId");
    });

Error Number:-2,State:0,Class:11 Execution Timeout Expired.
The timeout period elapsed prior to completion of the operation or the server is not responding.

当我同时尝试使用 CompanyCustomer 和 CompanySupplier 时,出现了另一个错误

Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong.

我还尝试为该关系创建一个新对象,并让 Company 对象持有一个 CompanyCustomers 列表,但是当我用它更新数据库时,我得到了一个包含三列的连接-table。

public class CompanyCustomer
{
    [Key, Column(Order = 0)]
    [ForeignKey("Company")]
    public string CompanyId { set; get; }
    [Key, Column(Order = 1)]
    [ForeignKey("Customer")]
    public string CustomerId { set; get; }

    public virtual Company Company { set; get; }
    public virtual Company Customer { set; get; }
}

公司客户

| CompanyId | CustomerID | Company_Id |
|-----------|------------|------------|
| 1234      | 1234       | 1234       |

我不明白如何在同一实体之间建立多种关系类型。我可以在 fluent 的帮助下做到这一点 api 还是我必须重新设计我的模型?

您可以只使用属性来做到这一点。您的问题是您在错误的 属性 上使用了 [ForeignKey] 属性 - 它应该在导航属性上。

[ForeignKey(nameof(CompanyId))]
public virtual Company Company { set; get; }

[ForeignKey(nameof(CustomerId))]
public virtual Company Customer { set; get; }

此外,您可以将 [InverseProperty] 属性添加到模型的集合中。这有助于理解关系导航。

[InverseProperty(nameof(CompanyCustomer.Company))]
public virtual ICollection<Company> Customers { set; get; }

流畅配置

modelBuilder.Entity<Company>()
    .HasMany(c => c.Customers)
    .WithMany()
    .Map(m =>
    {
        m.ToTable("CompanyCustomer");
        m.MapLeftKey("CompanyId");
        m.MapRightKey("CustomerId");
    });

确实是配置第一个关系的正确方法。你需要为第二个做类似的事情:

modelBuilder.Entity<Company>()
    .HasMany(c => c.Suppliers)
    .WithMany()
    .Map(m =>
    {
        m.ToTable("CompanySupplier");
        m.MapLeftKey("CompanyId");
        m.MapRightKey("SupplierId");
    });

在我干净的 EF 测试环境(如果重要的话,最新的 EF6.1.3)中产生以下迁移:

CreateTable(
    "dbo.Company",
    c => new
        {
            Id = c.String(nullable: false, maxLength: 128),
            Name = c.String(),
        })
    .PrimaryKey(t => t.Id);

CreateTable(
    "dbo.CompanyCustomer",
    c => new
        {
            CompanyId = c.String(nullable: false, maxLength: 128),
            CustomerId = c.String(nullable: false, maxLength: 128),
        })
    .PrimaryKey(t => new { t.CompanyId, t.CustomerId })
    .ForeignKey("dbo.Company", t => t.CompanyId)
    .ForeignKey("dbo.Company", t => t.CustomerId)
    .Index(t => t.CompanyId)
    .Index(t => t.CustomerId);

CreateTable(
    "dbo.CompanySupplier",
    c => new
        {
            CompanyId = c.String(nullable: false, maxLength: 128),
            SupplierId = c.String(nullable: false, maxLength: 128),
        })
    .PrimaryKey(t => new { t.CompanyId, t.SupplierId })
    .ForeignKey("dbo.Company", t => t.CompanyId)
    .ForeignKey("dbo.Company", t => t.SupplierId)
    .Index(t => t.CompanyId)
    .Index(t => t.SupplierId);

这正是您想要的。

您遇到的异常情况如何,它们可能与您对数据库的实验有关。确保从干净的数据库开始或删除 Company 实体(如果存在 CompanyCustomer) , 相应的 DbSets 和流畅的配置, 更新数据库以清除以前的混乱并重试。