实体框架代码优先,空条目写入数据库

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

请参阅下面的代码示例,其中我尝试实现与 SQLite 数据库的代码优先连接。我正在使用 .NET 4.8(不是 Core)。所有列名和数据库表名都是正确的。

Id
是所有数据库表中唯一的主键。
Derived_B
Derived_A
的数据库表是不同的。两者都有
Id
Name
Information
列。

Widgets
表通过上面代码中未列出的附加整数列与
Id
中的
Derived_B
具有外键关系。我可以以编程方式创建
Derived_A
Derived_B
Widgets
的实例,将它们添加到
Example_DataContext
,然后调用
SaveChanges()

随后,

Derived_A
Widgets
的有效条目将写入数据库。
Widgets
表中的新条目与
Derived_B
表具有有效的外键关系。

这就是我陷入困境的地方——虽然条目数量似乎正确,但

Derived_B
中的新条目除了索引列之外都是空的。数据上下文的记录输出表明仅 ID 列被写入
Derived_B
。为什么?我错过了什么?

我希望

Derived_B
中的新行具有有效数据。

using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;

namespace entityExample
{

    class Baseclass
    {
        [Column(name:"Name")]
        public string name { get; internal set; }
        
        [Column(name: "Information")]
        public string information { get; internal set; }
    }

    [Table("Derived_A")]
    class Derived_A : Baseclass
    {
        [Column(name: "Id")]
        public int Id { get; set; }

        public Derived_A() {}
    }

    [Table("Derived_B")]
    class Derived_B : Derived_A
    {
        public Derived_B() {}

        public List<Widget> widgets { get; internal set; }
    }

    [Table("Widgets"]
    class Widget
    {
        [Column(name: "Id")]
        public int Id { get; set; }

        [Column(name: "Name")]
        public string name { get; internal set; }

        [Column(name: "Description")]
        public string description { get; internal set; }
    }


    class Example_DataContext : DbContext
    {
        public DbSet<Derived_A> Derived_As {get; set;}
        public DbSet<Derived_B> Derived_Bs { get; set;}
        public DbSet<Widget> Widgets { get; set;}
        
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
        
            modelBuilder.Entity<Derived_A>().ToTable("Derived_A");
            modelBuilder.Entity<Derived_B>().ToTable("Derived_B");
        }
    }
}

我的保存到数据库的代码:

foreach (Baseclass item in items)
{
    if (item is Derived_B derivedB)
    {
        dbContext.Derived_Bs.Add(derivedB);
    }
    if (item is Derived_A derivedA)
    {
        dbContext.Derived_As.Add(derivedA);
    }
}

dbContext.SaveChanges();
.net sqlite entity-framework ef-code-first
1个回答
0
投票

如果您希望每个子类包含共享列,您需要显式告诉 EF 使用 Table-per-Concrete 配置,否则它可能会假设由于 B 继承自 A,而 A 继承自 Base,那么 Base 或“ A”将包含名称和其他列,B 的 Id 将链接回 A 以将两者关联起来。

modelBuilder.Entity<Baseclass>().UseTpcMappingStrategy();
modelBuilder.Entity<Derived_A>().UseTpcMappingStrategy();

老实说,当涉及到 EF 实体时,我会避免深度继承,以及几乎任何继承。代码如下:

if (item is Derived_B derivedB)
{
    dbContext.Derived_Bs.Add(derivedB);
}
if (item is Derived_A derivedA)
{
    dbContext.Derived_As.Add(derivedA);
}

对于可维护性来说是一个值得注意的危险信号。

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