【问题标题】:Entity Framework Core Database First - Multiple Foreign keys to one tableEntity Framework Core Database First - 一个表的多个外键
【发布时间】:2018-04-18 17:45:19
【问题描述】:

背景资料

我目前正在使用 EF Core 使用数据库优先实现。

当前表格

Fizz
{
    [Id] INT
    [Category] varchar
    [Value] varchar
}

Buzz
{
    [Id] UniqueIdentifier
    [TypeId1] INT
    [TypeId2] INT
    CONSTRAINT [FK_Buzz_Fizz_1] FOREIGN KEY ([TypeId1] REFERENCES [Fizz][Id]) 
    CONSTRAINT [FK_Buzz_Fizz_2] FOREIGN KEY ([TypeId2] REFERENCES [Fizz][Id])
}

Fizz 当前充当查找表。这样做允许使用单个数据存储库按类别查找不同的值。

Buzz 是一个表,它有两个不同的类型值要存储,例如TypeId1 可以是 Fizz 中存在的品牌(id, Brands, Nestle),TypeId2 可以是 Fizz 中存在的风味(id, Flavors, Grape)。

问题

我搭建数据库来创建数据模型。 运行应用程序时发生以下情况:

InvalidOperationException:无法确定“Fizz”类型的导航属性“Buzz.TypeId1”表示的关系。手动配置关系,或使用“[NotMapped]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.Ignore”忽略此属性。

我想到的一个解决方案是将此查找表 (Fizz) 分解为多个表,这样可以通过不使用外键的重复类型来解析引用。

这将需要对当前数据存储库的逻辑进行重新设计,以访问多个表或拆分为多个数据存储库。

另一个解决方案是修改生成的 DBContext 并在 DataModel 上使用 DataAnnotations。我想避免这样做,因为将来会重新生成上下文和模型,并且这些更改将被覆盖。

有没有一种方法可以从具有多个外键的表生成数据模型到单个表,而无需修改生成的代码?

【问题讨论】:

  • 脚手架不会导致错误。它将在 OnModelCreating 中生成代码以正确配置关系。您正在删除一些生成的代码,因此会出现错误。
  • @Smit Right 这是错误消息告诉我的。我想避免修改 OnModelCreating 因为这也是生成的代码。 “您正在删除一些生成的代码,因此会出现错误。”怎么样?
  • 我尝试从您的模型中构建代码。由于双方都有多个导航,因此 EF 无法根据约定确定应该是什么关系。 (如错误所说)。因此,脚手架会在 OnModelCreating 中吐出代码来解决歧义。 OnModelCreating 中的代码不会出错。

标签: c# entity-framework-core asp.net-core-2.0 ef-database-first


【解决方案1】:

为了后代:

使用数据库方法,完成了数据库的脚手架来创建上下文和数据模型。

生成的数据模型(使用上面的示例表)看起来像这样 -

public partial class Buzz
{
    public Buzz()
    { }

    public Guid Id { get; set; }
    public int TypeId1 { get; set; }
    public int TypeId2 { get; set; }

    public Fizz TypeId1Fizz { get; set; }
    public Fizz TypeId2Fizz { get; set; }
}


public partial class Fizz
{
    public Fizz()
    { }

    public int Id { get; set; }
    public string Category { get; set; }
    public string Value { get; set; }

    public ICollection<Buzz> TypeId1Fizz { get; set; }
    public ICollection<Buzz> TypeId2Fizz { get; set; }
}

问题是 Buzz 中的关系无法解决。

解决办法

在数据库上使用脚手架时,所有模型都生成为指定文件夹的部分。我在另一个目录中为 Buzz 类创建了一个部分,该目录位于脚手架创建的目录内(确保命名空间匹配 VS 喜欢将目录名称添加到命名空间,而部分将不匹配)。

public partial class Buzz
{
    [NotMapped]
    public Fizz TypeId1Fizz { get; set; }
    [NotMapped]
    public Fizz TypeId2Fizz { get; set; }
}

但是 Leustherin 然后你就失去了使用 .Include for Fizz 的能力! EntityFramework 不会为您创建 SQL 连接语句,因此您必须额外访问 DB 以获得查找值!

要解决此问题,请覆盖数据存储库的 Get 或 GetAll 函数并创建您自己的连接语句。

我为什么选择这个解决方案

可维护性。

每当重新生成 DataModel 而不是出现运行时错误时,现在都会出现一个编译错误,提醒开发人员从生成的数据模型中删除额外的属性。

自动生成的文件没有其他修改。

没有为适应更改而进行重大架构更改。

我会尽力保持更新。

【讨论】:

    猜你喜欢
    • 2023-04-05
    • 1970-01-01
    • 2015-04-18
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    相关资源
    最近更新 更多