【问题标题】:EF Core 2 duplicate column created with foreign key relationship使用外键关系创建的 EF Core 2 重复列
【发布时间】:2018-09-02 14:56:17
【问题描述】:

我正在尝试使用 EF 核心 2 代码优先方法添加迁移。问题是,具有外键关系的实体是用一个外键 id 结尾带“1”的外键和一个具有相同名称但末尾没有 1 的冗余列创建的,这不是外键。

示例是我的 2 个类,Store 和 StoreVisit,如下所示:

商店

[Table("Store")]
public class Store
{
    public Store()
    {
        StoreVisits = new HashSet<StoreVisit>();
    }
    [Key]
    public int StoreId { get; set; }

    [StringLength(30)] 
    public string ShopName { get; set; }

    [StringLength(50)]
    public string ShopKeeper { get; set; } 

    public string ContactNo { get; set; }

    [StringLength(70)]
    public string Address { get; set; }

    [StringLength(20)]
    public string Street { get; set; }

    [StringLength(50)] 
    public string City { get; set; }

    public IEnumerable<StoreVisit> StoreVisits { get; set; }
}

实体店光顾

[Table("StoreVisit")]
public class StoreVisit
{

    [Key]
    public int StoreVisitId { get; set; }

    [StringLength(50)]
    public string Location { get; set; }

    [StringLength(50)]
    public string Notes { get; set; }

    [DataType(DataType.Time)]
    public DateTime StartTime { get; set; }

    [DataType(DataType.Time)]
    public DateTime EndTime { get; set; }

    public Store Store { get; set; }

}

在数据库中创建了访问类,其列如下图所示:

如您所见,StoreVisit 表包含“StoreId1”列(实际外键)和“StoreId”列(非外键)。

我什至配置了与 Fluent API 的关系如下:

            modelBuilder.Entity<Store>()
            .HasMany(c => c.StoreVisits)
            .WithOne(e => e.Store)
            .IsRequired();

谁能帮忙。

【问题讨论】:

  • 图片中缺少某些内容。你的StoreVisit 类中有StoreId 属性吗?或者这里没有显示一些流畅的配置?
  • 同意。 EF 不会自行创建StoreId 列,因为它是bigintStore 上的PK 只是int。即使您的实体/配置存在导致 EF 两次创建 FK 属性的问题,也将是两个 int 列。它是bigint 的事实意味着您在某处手动添加。
  • 我遇到了这个问题。这归结为我在执行流畅的 API 级联删除限制的方式上出现了故障。我使用不正确的 HasForeignKey 建立了关系,最终结果是 EF 开始创建重复字段。

标签: entity-framework-core asp.net-core-2.0 entity-framework-core-migrations


【解决方案1】:

需要在类上定义外键。

[Table("StoreVisit")]
public class StoreVisit
{

    [Key]
    public int StoreVisitId { get; set; }

    public int StoreId { get; set; }

    [StringLength(50)]
    public string Location { get; set; }

    [StringLength(50)]
    public string Notes { get; set; }

    [DataType(DataType.Time)]
    public DateTime StartTime { get; set; }

    [DataType(DataType.Time)]
    public DateTime EndTime { get; set; }

    public Store Store { get; set; }

}

将外键引用添加到 Fluent API 也会造成伤害。

modelBuilder.Entity<Store>()
            .HasMany(c => c.StoreVisits)
            .WithOne(e => e.Store)
            .HasForeignKey(e => e.StoreId)
            .IsRequired();

【讨论】:

  • 这里的诀窍是问题中的 HasForeignKey 丢失了。
【解决方案2】:

注意,Entity Framework Core 足够智能来检测你的类之间的关系,如果你使用它的conventions,这些关系将变成具有关系的数据库表。所以这是多余的StoreId属性上面使用像[Key]这样的注解。

第二件事,作为建议,请尝试为类或属性使用简单明了的名称,因为它们可能与 EF 自动创建的名称相似。例如,在您的情况下,我更愿意避免在 StoreVisit 类名中再次使用 store(例如,在 多对多 关系的情况下,派生表被命名为 StoreVisit就像你雇用的那样,只是没有's',虽然你的情况是一对多),

最后的提示是出现多余的StoreId列的原因。实际上,在您的情况下,没有必要使用 Fluent API,因为 EF 可以检测到这种关系。此外,您为modelBuilder 编写了错误的配置。 所以删除它并让 EF 生成它(除非您计划有完全定义的关系以在您的代码中利用它的优势)。

  • StoreId 是您告诉 EF 生成它的一个(如 required) 在modelBuilder
  • StoreId1 是 EF 自动生成的列(外键),基于一个 到很多关系。附加“1”是为了避免列名重复。

【讨论】:

  • 我明白了,我在这里遇到了同样的问题。首先,我正在创建导航属性和相应的外键,例如: Catalog { int CatalogId;列表 项目 };项目 { int ItemId, int CatalogId, Catalog parentCatalog };有了这个配置的关系就可以很好地设置。然后我添加了流畅的 API 外键关系,就像我需要级联删除行为一样。我的服务依赖于 Item 中的 CatalogId 字段,因此在使用 fluent api 配置后我无法将其删除。现在 EF Core2 生成 CatalogId 和 CatalogId1 FK,包括 int 和第二个 w/o Cascade。如何应对?
  • 我在这里找到了答案:stackoverflow.com/a/52957270。只需使用 Entity.HasOne 和 lambda 来指定确切的元素,否则 EF 将创建新元素。
猜你喜欢
  • 2020-10-03
  • 2021-03-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 2020-12-10
  • 2012-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多