使用复合键与实体框架核心和使用其中的一部分作为外键。

问题描述 投票:0回答:1

我正试图制作几个具有复合键的表(如下例)。我一直在使用代码优先的方法来实现这个目标,但是我希望这些复合键能够层叠到子表。我们的想法是,每个子实体都有和它的父实体一样的复合键,再加上一列。

| PurchaseOrder |
| ------------- |
| Company (PK)  |
| PONum (PK)    |

| PuchaseOrderLine |
| ---------------- |
| Company (PK/FK)  |
| PONum (PK/FK)    |
| POLine (PK)      |

从技术上讲,PurchaseOrder表会做类似于公司表的事情,但这对我来说稍微不那么重要,我想如果我能够搞清楚POLine到PO的连接,我也会搞清楚这个问题。

这是我目前的尝试。

// OnModelCreating method in my class that inherits IdentityDbContext<IdentityUser> 
protected override void OnModelCreating(ModelBuilder builder)
{
      base.OnModelCreating(builder);

      builder.Entity<Company>()
          .DefaultConfigure(c => new { c.Name });

      builder.Entity<PurchaseOrder>()
          .DefaultConfigure(p => new { p.Company, p.PONum })
          .HasMany(e => e.PurchaseOrderLines)
          .WithOne(e => e.PurchaseOrder);

      builder.Entity<PurchaseOrderLine>()
          .DefaultConfigure(p => new { p.Company, p.PONum, p.LineNum })
          .HasOne(e => e.PurchaseOrder)
          .WithMany(e => e.PurchaseOrderLines);
}

// My DefaultConfigure extension method
public static EntityTypeBuilder<T> DefaultConfigure<T>(this EntityTypeBuilder<T> builder, Expression<Func<T, object>> keyExpression)
    where T : AuditableEntity
{
    // Rename table to the types name
    builder.ToTable(typeof(T).Name.ToLower());

    // Configure the keys they passed in
    builder.HasKey(keyExpression);

    // Configure the default alternate key
    builder.HasAlternateKey(i => new { i.RowId });

    // Give the builder back
    return builder;
}

当我进行迁移并更新数据库时 我的PurchaseOrderLine表是这样的:


| COLUMN_NAME          | CONSTRAINT_NAME                                                            |
| -------------------- | -------------------------------------------------------------------------- |
| RowId                | AK_PurchaseOrderLine_RowId                                                 |
| PurchaseOrderCompany | FK_PurchaseOrderLine_PurchaseOrder_PurchaseOrderCompany_PurchaseOrderPONum |
| PurchaseOrderPONum   | FK_PurchaseOrderLine_PurchaseOrder_PurchaseOrderCompany_PurchaseOrderPONum |
| Company              | PK_PurchaseOrderLine                                                       |
| LineNum              | PK_PurchaseOrderLine                                                       |
| PONum                | PK_PurchaseOrderLine                                                       |

EFCore只是用默认的命名方式添加了两个新的列,而没有使用我已有的列。 有没有什么办法可以让efcore用代码优先的方法来做这样的事情?

c# sql entity-framework ef-code-first ef-core-3.1
1个回答
1
投票

回答你的具体问题

有没有办法让efcore用代码优先的方法来做这样的事情?

当然有。只是 常规外键名 显然是不行的,所以你必须明确地配置FK属性(通过 HasForeignKey fluent API)。)

例如,要么

builder.Entity<PurchaseOrderLine>()
    .DefaultConfigure(p => new { p.Company, p.PONum, p.LineNum })
    .HasOne(e => e.PurchaseOrder)
    .WithMany(e => e.PurchaseOrderLines)
    .HasForeignKey(e => { e.Company, e.PONum }); // <--

builder.Entity<PurchaseOrder>()
    .DefaultConfigure(p => new { p.Company, p.PONum })
    .HasMany(e => e.PurchaseOrderLines)
    .WithOne(e => e.PurchaseOrder)
    .HasForeignKey(e => { e.Company, e.PONum }); // <--

请注意,这两个 Has With 对代表着一种相同的关系,所以为了避免配置冲突,最好只在一个地方做。


0
投票

不要这样做。 使用自动递增的主键。 在父表中查找你需要的值。

复合主键只是让外键变得很麻烦。 如果广泛用作外键,它们的效率也较低,而且一般会占用更多的空间。

所以。PurchaseOrder 应有 PurchaseOrderId. 那么 PurchaseOrderLine 应指 PurchaseOrderId 并在需要公司等相关信息时,查询该信息。

© www.soinside.com 2019 - 2024. All rights reserved.