【问题标题】: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)。
  • 我添加了另一个尝试,看看它是否能更好地捕捉到我想象的映射方式

标签: c# entity-framework-core entity-relationship entity-relationship-model


【解决方案1】:

注意:... EF 设置不会影响 SQL 对象的实际创建。

这是不正确的。将属性添加到派生类后,您需要使 EF 与数据库同步 - 换句话说,更新表和关系。一旦你这样做了,EF 会尝试将你的层次结构映射到表(假设你使用 EF Core 5),这就是为什么你会在 Discriminator 列(这是 EF 处理层次结构的方式)出现错误。

现在,只有在 DbContext 中有 ProjectB.ClassA 时才会发生这种情况。你?如果你不这样做,那么根本原因就不同了。请出示DbContext 代码。您暗示那里也有基类和派生类 - 这有点令人费解,可能是问题的真正原因。

另外,请显示您遇到的错误

【讨论】:

  • 我在描述我的首选结果方面做得不好。基本上,我希望有一个项目,它有一个 DbContext ,其中包含一些表和其他项目的基本信息,以便能够从该基本信息继承并将导航属性添加到它们的特定表中。我不希望基本上下文和定义必须知道所有具有依赖外键的表。
  • DbContext(代表数据库)和许多DbSets(代表表)。你不需要继承DbContext。您可以DbSet 类派生,只要您不将派生类本身标记为DbSet - 它们就不会保留在数据库中。但看起来您想要保留派生类的信息 - “导航属性”映射到外键。 “我不希望基本上下文知道表......”这句话没有意义。也许从头开始,解释你真正想做的事情!
  • 我正在尝试 Felix D:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多