代码之家  ›  专栏  ›  技术社区  ›  FireWingLead

如何避免实体框架代码首先使用不属于模型的派生类

  •  3
  • FireWingLead  · 技术社区  · 10 年前

    下面是我正在做什么、正在发生什么以及应该发生什么的一般示例:

    首先,我声明我的代码优先模型,类似于:

    上下文:

    namespace Models {
        public class MyContext : DbContext
        {
            public DbSet<ClassA> ClassA { get; set; }
            public DbSet<ClassB> ClassB { get; set; }
    
            public MyContext()
                : base("name=MyContext")
            {
            }
        }
    }
    

    A类和B类:

    namespace Models {
        public class ClassA
        {
            public int ClassAID { get; set; }
            public string BaseAVal { get; set; }
            public virtual ICollection<ClassB> ClassBChildren {get; set; }//Relation Property
        }
        public class ClassB
        {
            public int ClassBID { get; set; }
            public int ClassAID { get; set; }//Foreign Key
            public string BaseBVal { get; set; }
            public virtual ClassA ClassAParent { get; set; }//Relation Property
        }
    }
    

    现在在其他地方,在另一个命名空间中,我有从模型类派生的用于不同目的的类。

    派生类:

    namespace CalculatedModels {
        public class DerivedClassA : ClassA
        {
            string SecondAVal { get; set; }
            public static DerivedClassA fromDBItem(ClassA dbItem) {
                //Create a DerivedClassA
                //Copy over inherited properties from dbItem (via Reflection)
                //Calculate its non-inherited properties
                //return it
            }
            public ClassA toDBItem() {
                //Create a ClassA
                //Copy over inherited properties from this (via Reflection)
                //return it
            }
        }
        public class DerivedClassB : ClassB
        {
            string SecondBVal { get; set; }
            //Conversion functions similar to those in DerivedClassA go here...
        }
    }
    

    当我让EntityFramework从此模型生成数据库时,问题就出现了。我不希望它包含派生类中的任何内容。它们不适合数据库自己关注!否则我为什么要将它们放在一个完全不同的命名空间中,并使上下文中的集合是非扩展的基类型?表格应如下所示:

    Table: ClassA
        ---Columns---
        ClassAID (PrimaryKey, int, not null)
        BaseAVal (nvarchar(max), null)
    
    Table: ClassB
        ---Columns---
        ClassBID (PrimaryKey, int, not null)
        ClassAID (ForeignKey, int, not null)
        BaseBVal (nvarchar(max), null)
    

    但EF坚持通过添加派生类的新声明属性来破坏我的预期模式,如下所示:

    Table: ClassA
        ---Columns---
        ClassAID (PrimaryKey, int, not null)
        BaseAVal (nvarchar(max), null)
        SecondAVal (nvarchar(max), null) --This should NOT be here!!
        Discriminator (nvarchar(128)) --Neither should this!!
    
    Table: ClassB
        ---Columns---
        ClassBID (PrimaryKey, int, not null)
        ClassAID (ForeignKey, int, not null)
        BaseBVal (nvarchar(max), null)
        SecondBVal (nvarchar(max), null) --This should NOT be here!!
        Discriminator (nvarchar(128)) --Neither should this!!
    

    正如您所看到的,它将派生类作为模型和/或数据库系统的一部分,尽管模型中没有任何内容与它们相关。他们参考模型中的东西,而不是相反的方式——永远。我不想让它使用它们!我如何防止它这样做?

    1 回复  |  直到 10 年前
        1
  •  5
  •   SWilko    10 年前

    实体框架正在做它应该做的事情,因为您的设置遵循每层次表(TPH)继承模式。

    鉴别器 以便数据库能够区分何时将ClassA或DervivedClassA添加到数据库中

    可以使用NotMapped属性停止EF映射派生类。 添加以下命名空间

    using System.ComponentModel.DataAnnotations.Schema;
    

    衍生类别B

    [NotMapped]
    public class DerivedClassB : ClassB
    {
        string SecondBVal { get; set; }
        //Conversion functions similar to those in DerivedClassA go here...
    }