首页 文章

实体框架核心数据库优先 - 一个表的多个外键

提问于
浏览
1

背景资料

我目前正在使用数据库优先实现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) .

问题

我支持db来创建数据模型 . 运行应用程序时,会发生以下情况:

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

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

这将需要重新处理当前数据存储库的逻辑,以访问多个表或拆分为多个数据存储库 .

另一种解决方案是修改生成的DBContext并在DataModel上使用DataAnnotations . 我想避免这样做,因为将来会重新生成Context和Models,这些更改将被覆盖 .

有没有办法从一个表生成一个数据模型,该表具有多个外键到一个表而不必修改生成的代码?

1 回答

  • 1

    For posterity:

    使用数据库方法,完成db的脚手架以创建上下文和数据模型 .

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

    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中的关系无法解决 .

    解决方案

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

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

    但是Leustherin然后你失去了利用的能力 . 包括Fizz! EntityFramework不会为您创建SQL连接语句,因此您必须额外访问数据库才能获得查找值!

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

    为什么选择此解决方案

    Maintainability.

    无论何时重新生成DataModel而不是获得运行时错误,现在都存在编译错误,提醒开发人员从生成的数据模型中删除额外的属性 .

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

    没有进行重大架构更改以适应更改 .

    我会尽力保持更新 .

相关问题