惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
博客园 - 叶小钗
爱范儿
爱范儿
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
美团技术团队
T
Tailwind CSS Blog
博客园 - 司徒正美
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
量子位
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
V
Visual Studio Blog
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell

博客园 - JerryZhao

[转载]jQuery对象VS DOM对象 [Reference] Navigation on Matrix Subtotal [Refereces]Creating an .ini File for the Application Manager [Refereces] Developing and Deploying Pocket PC Setup Applications [References]More on device app installs - Installing a Windows Mobile device application from a desktop MSI [References]Deploying .NET Compact Framework 2.0 Applications with .cab and .msi Files [References]Installing Multiple CAB Files [Reference]Wix Restart IIS code snippet [Reference] Windows Installer XML (WiX) 3.0 Snippets [Reference] Casle Demo App: Midway Summary [ActiveRecord] 之五:ActiveRecordMediator [Reference][ActiveRecord] 之四:Cascade [Referece][ActiveRecord] 之七:多数据库配置 [Reference] [Castle AR] 5. Base Relations [Reference][Castle AR] 3. Validate [Reference][Castle AR] 2. ActiveRecord [Reference][Castle AR] 1. Starter [reference][Castle AR] 4. CRUD [Reference]NHibernateDataSource: A DataSourceControl for ASP.NET 2.0
[Reference][ActiveRecord] 之六:继承
JerryZhao · 2008-01-23 · via 博客园 - JerryZhao

http://www.rainsts.net/article.asp?id=244
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 = "班主任"
}

-----------------

附:本文所有演示代码使用 2006-01-01 发布的 Castle ActiveRecord Beta3 版本。
Castle ActiveRecord 在发布 1.0 版本前可能有很多较大的变化,如演示代码无法编译,建议您参考最新版本的相关文档。

[最后修改由 yuhen, 于 2006-09-12 14:02:47]