[ActiveRecord] 之六:继承

来源:互联网 发布:淘宝怎么解决管控纪录 编辑:程序博客网 时间:2024/05/01 06:32
 ActiveRecord 支持继承体系,我们看看几种不同的实现方式。

1. 无关联继承
public class Person{    private int id;    [PrimaryKey(PrimaryKeyType.Identity)]    public int Id    {        get { return id; }        set { id = value; }    }    private string name;    [Property(NotNull=true)]    public string Name    {        get { return name; }        set { name = value; }    }}[ActiveRecord]public class Student : Person{    private int grade;    [Property]    public int Grade    {        get { return grade; }        set { grade = value; }    }}[ActiveRecord]public class Teacher : Person{    private string job;    [Property]    public string Job    {        get { return job; }        set { job = value; }    }}


调用 ActiveRecordStarter.CreateSchema(); ,你会发现数据库里面分别生成了 Student 和 Teacher 数据表,每个表都拥有基类(Person)的字段,相互没有关联。这种继承方式下,我们无法通过 Find(typeof(Person)) 来返回所有人(Student & Teacher)。严格来说,我们根本无法调用此方法,因为我们不能为 Person 添加 ActiveRecordAttribute。

此方式仅仅是为了代码重用而已,并没有业务上的关联。

== 数据表结构 ==

Student Table{    Id    Name    Grade}Teacher Table{    Id    Name    Job}


执行插入对象测试代码

Student s = new Student();s.Name = "student1";s.Grade = 2;ActiveRecordMediator.Create(s);Teacher t = new Teacher();t.Name = "teacher1";t.Job = "班主任";ActiveRecordMediator.Create(t);


结果

Student Table{    Id = 1    Name = "student1"    Grade = 2}Teacher Table{    Id = 1    Name = "teacher1"    Job = "班主任"}

2. 单表关联继承

我们使用 ActiveRecordAttribute 内置属性更改上面的例子,使其成为关联继承。

[ActiveRecord(DiscriminatorColumn = "Type", DiscriminatorType = "String", DiscriminatorValue = "Person")]public class Person{    private int id;    [PrimaryKey(PrimaryKeyType.Identity)]    public int Id    {        get { return id; }        set { id = value; }    }    private string name;    [Property(NotNull=true)]    public string Name    {        get { return name; }        set { name = value; }    }}[ActiveRecord(DiscriminatorValue = "Student")]public class Student : Person{    private int grade;    [Property]    public int Grade    {        get { return grade; }        set { grade = value; }    }}[ActiveRecord(DiscriminatorValue = "Teacher")]public class Teacher : Person{    private string grade;    [Property]    public string Job    {        get { return grade; }        set { grade = value; }    }}


你会发现数据库里面仅生成了一个Person表。

== 数据表结构 ==

Student Person{    Id    Type // 由 Person[DiscriminatorColumn...] 特性生成!    Name    Grade    Job}


执行插入对象测试代码
结果

Person Table{    // Record 1-----------------    Id = 1    Type = "Student"    Name = "student1"    Grade = 2    Job = <NULL>    // Record 2-----------------    Id = 2    Type = "Teacher"    Name = "teacher1"    Grade = <NULL>    Job = "办主任"}


在基类定义一个 DiscriminatorColumn 特性,子类通过写入不同的 DiscriminatorValue 来达到区分不同子类型的目的。

这种方式解决了多态查询的问题,但当子类新增属性较多,而且多个子类属性差别较大的情况下,数据库空间浪费会比较严重。同时由于对于不属于当前类的数据库字段插入NULL,可能会造成插入时发生错误,触发异常(比如我们将 Teacher.Job 的特性改为 Property(NotNull=true),那么我们保存Student对象到数据库时就会触发异常)。

我们对基类和子类进行查询测试

foreach Person p in (Person[])ActiveRecordMediator.FindAll(typeof(Person))){    Console.WriteLine("Person {0}:{1}", p.Id, p.Name);}foreach (Student p2 in (Student[])ActiveRecordMediator.FindAll(typeof(Student))){    Console.WriteLine("Student {0}:{1}", p2.Id, p2.Name);}foreach (Teacher p3 in (Teacher[])ActiveRecordMediator.FindAll(typeof(Teacher))){    Console.WriteLine("Teacher {0}:{1}", p3.Id, p3.Name);}

输出
Person 1:student1
Person 2:teacher1
Student 1:student1
Teacher 2:teacher1

建议你继续往下看,或许下面的方式更适合你。

3. 多表关联继承

[ActiveRecord, JoinedBase]public class Person{    private int id;    [PrimaryKey(PrimaryKeyType.Identity)]    public int Id    {        get { return id; }        set { id = value; }    }    private string name;    [Property(NotNull=true)]    public string Name    {        get { return name; }        set { name = value; }    }}[ActiveRecord]public class Student : Person{    [JoinedKey("Id")]    public int StudentId    {        get { return base.Id; }        set { base.Id= value; }    }            private int grade;    [Property]    public int Grade    {        get { return grade; }        set { grade = value; }    }}[ActiveRecord]public class Teacher : Person{    [JoinedKey("Id")]    public int TeacherId    {        get { return base.Id; }        set { base.Id= value; }    }            private string grade;    [Property]    public string Job    {        get { return grade; }        set { grade = value; }    }}


我们注意到为 Person 添加了 ActiveRecordAttribute 和 JoinedBaseAttribute 特性,同时为子类 Student 和 Teacher 添加了一个附加了 JoinedKeyAttribute 的 Id 字段。此继承模式会分别生成 Person、Student 和 Teacher 三个数据表。Person 存储了基类的所有字段,子类表仅包含子类增加的属性和Id映射字段。此继承方式下,我们查找 Person 时,会同时返回 Student 和 Teacher记录。

== 数据表结构 ==

Person Table{    Id    Name}Student Table{    StudentId    Grade}Teacher Table{    TeacherId    Job}


执行插入对象测试代码
结果

Person Table{    // Record 1---    Id = 1    Name = "student1"    // Record 1---    Id = 2    Name = "teacher1"}Student Table{    Id = 1    Grade = 2}Teacher Table{    Id = 2    Job = "班主任"}




 

原创粉丝点击