具有额外配置的导航属性的模型派生类
Posted
技术标签:
【中文标题】具有额外配置的导航属性的模型派生类【英文标题】:Derived class from model with additionally configured navigational properties 【发布时间】:2021-11-03 17:37:15 【问题描述】:注意:我的数据库已经用 sql 编写,EF 设置不会影响 SQL 对象的实际创建。
我正在尝试创建其他项目可以继承的“基础”上下文和模型,希望基础上下文和模型不需要修改,而是随着其他关系的建立而扩展。这是我目前的尝试
文件 1:
namespace BaseProject.Models
public class ClassA
public int Id get;set;
public string Value get; set;
public void DoConfiguring(ModelBuilder modelBuilder)
// do setup to define the key and table
文件 2:
namespace ProjectB.Models
public class ClassA: BaseProject.Models.ClassA
public ClassC NavPropertyToAnotherClass get; set;
public void DoConfiguring(ModelBuilder modelBuilder)
// do setup for nav property here
在这种情况下,BaseProject 的所有模型都已配置,然后 ProjectB 的所有模型都已配置。我希望将所有数据都保存在 1 个表中,如 ClassA 配置中定义的那样。我没有添加任何其他列或信息。我只是希望能够像使用 ClassA 一样使用 ClassB,但需要设置额外的导航属性。
我遇到了鉴别器问题和其他一些正在停止的小问题。是我的设置错误,还是这种类型的问题目前无法通过继承和 EF Core 解决。
编辑: 最终目标是能够在建立新关系时向继承的模型添加导航属性,以便基本模型和实体几乎可以保持不变。
另一种尝试来解释我的设想。
//----------- File ---------------//
namespace BaseProject.Models
public class Person
public int Id get;set;
public string FirstName get; set;
public string LastName get; set;
public int? ParentOneId get; set;
public int? ParentTwoId get; set;
public Person ParentOne get; set;
public Person ParentTwo get; set;
public ICollection<Person> ChildrenOne get; set;
public ICollection<Person> ChildrenTwo get; set;
public void OnModelCreating(ModelBuilder modelBuilder)
var builder = modelBuilder.Entity<Person>();
builder.HasMany(l => l.ChildrenOne)
.WithOne(co => co.ParentOne)
.HasForeignKey(co => co.ParentOneId);
builder.HasMany(l => l.ChildrenTwo)
.WithOne(co => co.ParentTwo)
.HasForeignKey(co => co.ParentTwoId);
builder.ToTable("dbo", "Person");
builder.HasKey(f => f.Id);
//--------------------------//
//----------- File ---------------//
namespace BaseProject.Contexts
public class BaseContext : DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
new Person().OnModelCreating(modelBuilder);
base.OnModelCreating(modelBuilder);
//--------------------------//
//----------- File ---------------//
namespace ExtraCurricularProject.Models
public class ExtraCurricular
public int Id get; set;
public string Name get; set;
// other stuff
public ICollection<PersonExtraCurricular> PersonExtraCurriculars get; set;
public void OnModelCreating(ModelBuilder modelBuilder)
var builder = modelBuilder.Entity<ExtraCurricular>();
builder.ToTable("dbo", "ExtraCurricular");
builder.HasKey(f => f.Id);
//----------------------------//
//----------- File ---------------//
namespace ExtraCurricularProject.Models
public class Person : BaseProject.Models.Person
public ICollection<PersonExtraCurricular> PersonExtraCurriculars get; set;
public void OnModelCreating(ModelBuilder modelBuilder)
//--------------------------//
//----------- File ---------------//
namespace ExtraCurricularProject.Models
public class PersonExtraCurricular
public int PersonId get; set;
public int ExtraCurricularId get; set;
public Person Person get; set;
public ExtraCurricular ExtraCurricular get; set;
public void OnModelCreating(ModelBuilder modelBuilder)
var builder = modelBuilder.Entity<PersonExtraCurricular>();
builder.HasOne(pec => pec.Person)
.WithMany(p => p.PersonExtraCurriculars)
.HasForeignKey<PersonExtraCurricular>(pec => pec.PersonId);
builder.HasOne(pec => pec.ExtraCurricular)
.WithMany(ec => ec.PersonExtraCurriculars)
.HasForeignKey<PersonExtraCurricular>(pec => pec.ExtraCurricularId);
builder.ToTable("dbo", "PersonExtraCurricular");
builder.HasKey(pec => new pec.PersonId, pec.ExtraCurricularId );
//--------------------------//
//----------- File ---------------//
namespace ExtraCurricularProject.Contexts
public class ExtraCurricularContext : BaseContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
new Person().OnModelCreating(modelBuilder);
new ExtraCurricular().OnModelCreating(modelBuilder);
new PersonExtraCurricular().OnModelCreating(modelBuilder);
base.OnModelCreating(modelBuilder);
//--------------------------//
尝试使用这种类型的模式它说我需要一个鉴别器,但我不想让 BaseProject.Models.Person 和 ExtraCurricularProject.Models.Person 带回不同的数据,我只想要 ExtraCurricularProject.Models.Person能够访问那些其他导航属性。
【问题讨论】:
这些DoConfiguring
方法在哪里运行?目前尚不清楚这两个类是否都已配置。 (假设第二个ClassA
实际上是ClassB
)。
我添加了另一个尝试,看看它是否能更好地捕捉到我想象的映射方式
【参考方案1】:
注意:... EF 设置不会影响 SQL 对象的实际创建。
这是不正确的。将属性添加到派生类后,您需要使 EF 与数据库同步 - 换句话说,更新表和关系。一旦你这样做了,EF 会尝试将你的层次结构映射到表(假设你使用 EF Core 5),这就是为什么你会在 Discriminator
列(这是 EF 处理层次结构的方式)出现错误。
现在,只有在 DbContext
中有 ProjectB.ClassA
时才会发生这种情况。你?如果你不这样做,那么根本原因就不同了。请出示DbContext
代码。您暗示那里也有基类和派生类 - 这有点令人费解,可能是问题的真正原因。
另外,请显示您遇到的错误
【讨论】:
我在描述我的首选结果方面做得不好。基本上,我希望有一个项目,它有一个 DbContext ,其中包含一些表和其他项目的基本信息,以便能够从该基本信息继承并将导航属性添加到它们的特定表中。我不希望基本上下文和定义必须知道所有具有依赖外键的表。 有DbContext
(代表数据库)和许多DbSet
s(代表表)。你不需要继承DbContext
。您可以从DbSet
类派生,只要您不将派生类本身标记为DbSet
- 它们就不会保留在数据库中。但看起来您想要保留派生类的信息 - “导航属性”映射到外键。 “我不希望基本上下文知道表......”这句话没有意义。也许从头开始,解释你真正想做的事情!
我正在尝试 Felix D:以上是关于具有额外配置的导航属性的模型派生类的主要内容,如果未能解决你的问题,请参考以下文章