【问题标题】:TPC Inheritance 1 base class with 2 children inheriting, 1 class property computed, other class property not computedTPC 继承 1 个基类,2 个子类继承,1 个类属性已计算,其他类属性未计算
【发布时间】:2018-08-03 18:01:04
【问题描述】:

我正在从事一个有两个类和一个基类的项目。基类包含项目和程序模型之间的所有公共属性。项目通过 ProgramID 列与程序相关联。 Projects 有一个 ProgramID 的可编辑字段,让用户可以选择他们想要将项目关联到的程序(并非所有项目都有程序,这就是它可以为空的原因)。

本质上,我希望项目能够读取和写入数据库,而程序只能读取(未设置)。这可能与 TPC 继承有关吗?欢迎任何建议。如果需要更多信息,我很乐意提供。提前感谢您的帮助!

基类

public abstract class PMBase
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual int ProjectID { get; set; }

    public virtual int? ProgramID { get; set; }

    public virtual Program Program { get; set; }

    //Omitted rest of Model
}

程序类

public class Program : PMBase
{
    [Column("PMGroupID")]
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public override int? ProgramID { get { return ProjectID; } set { value = null; } }

    //NOTE: Database column names were from legacy changes.  I wish we could change this, but we do not have time.
    [Column("ProgramID")]
    public override int ProjectID { get; set; }

    public virtual ICollection<PMBase> Projects { get; set; }

    //Omitted rest of Model
}

项目类

public class Project : PMBase
{
    [Display(Name = "Program Number & Name")]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public override int? ProgramID { get; set; }

    //Omitted rest of Model
}

dbContext 映射

modelBuilder.Entity<Project>()
  .Map(prj =>
  {
    prj.MapInheritedProperties();
    prj.ToTable("Projects");
  });

modelBuilder.Entity<Program>()
  .Map(pgm =>
  {
    pgm.MapInheritedProperties();
    pgm.ToTable("Programs");
  });

modelBuilder.Entity<PMBase>()
  .HasOptional(prj => prj.Program)
  .WithMany(pgm => pgm.Projects)
  .HasForeignKey(prj => prj.ProgramID);

看到的错误消息

在尝试各种事情时会出现这些错误。当我看到 UNION 错误时,我觉得我很接近,但似乎无法超越。

无法修改列“PMGroupID”,因为它要么是计算列,要么是 UNION 运算符的结果。

覆盖外键组件“ProgramID”不是“Project”类型的声明属性。验证它没有被明确地从模型中排除,并且它是一个有效的原始属性。

无法确定相关操作的有效顺序。由于外键约束、模型要求或存储生成的值,可能存在依赖关系。

【问题讨论】:

  • 为什么要在不同的具体类中使用相同的属性名来表示不同的东西?您可以在 Program 和 Project 中拥有与主键列和外键列关联的唯一命名属性,并且如果您确实需要引用 PMBase.ProgramID 使其成为 PMBase 中的抽象属性,派生自每个具体类中的正确列,并被忽略通过实体框架。
  • @Rattle - 我目前是这样设置的,因为我们有一个通过表达式树的搜索功能,它必须具有从 PMBase 继承的属性。我认为有一种方法可以解决这个问题。您能否提供一个引用抽象属性的具体属性的示例?可能是星期一和早些时候,但我没有关注。

标签: c# entity-framework


【解决方案1】:

在接受 Rattles 的建议后,我能够让模型按预期工作。

通过创建一个抽象的 getter,我能够成功地将它用作我的搜索函数的属性。使用 getter 读取具体属性,它使模型更易于使用/维护。然后,我只能在 Project 中使用 ProgramID 属性。谢谢拉特的建议!

基类

public abstract class PMBase
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual int ProjectID { get; set; }

    [NotMapped]
    public virtual int? PMGroupID { get { return ProgramIDGetter(); } }
    public abstract int? ProgramIDGetter();


//Omitted rest of Model
}

程序类

public class Program : PMBase
{
    public override int? ProgramIDGetter()
    {
        return this.ProjectID;
    }

    //NOTE: Database column names were from legacy changes.  I wish we could change this, but we do not have time.
    [Column("ProgramID")]
    public override int ProjectID { get; set; }

    public virtual ICollection<Project> Projects { get; set; }

    //Omitted rest of Model

}

项目类

public class Project : PMBase
{

    public override int? ProgramIDGetter()
    {
        return this.ProgramID;
    }

    [Display(Name = "Program Number & Name")]
    public override int? ProgramID { get; set; }

    //Omitted rest of Model
}

dbContext 映射

modelBuilder.Entity<Project>()
  .Map(prj =>
  {
    prj.MapInheritedProperties();
    prj.ToTable("Projects");
  });

modelBuilder.Entity<Program>()
  .Map(pgm =>
  {
    pgm.MapInheritedProperties();
    pgm.ToTable("Programs");
  });

modelBuilder.Entity<Project>()
  .HasOptional(prj => prj.Program)
  .WithMany(pgm => pgm.Projects)
  .HasForeignKey(prj => prj.ProgramID);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多