[导入]Castle ActiveRecord学习记录 - 处理继承关系

原文链接:http://www.cnblogs.com/debug1/archive/2006/05/16/413757.html

  在面向对象的设计中继承是少不了的,那么如何在AR里来设计有继承关系的实体类呢?查看相关文档并做了一些尝试,例子如下(例子很简陋,仅是单纯考虑继承的实现)。其中有理解错误的地方还肯请大家指正。


一、使用 subclass

[ActiveRecord("Entity"), JoinedBase]
public class Entity : ActiveRecordBase
{
private int id;
private string name;
public Entity()
{
}
[PrimaryKey(PrimaryKeyType.Assigned, "id")]
public int Id
{
get { return id; }
set { id = value; }
}
[Property]
public string Name
{
get { return name; }
set { name = value; }
}
public new static void DeleteAll()
{
ActiveRecordBase.DeleteAll(typeof(Entity));
}
public new static Entity[] FindAll()
{
return (Entity[])ActiveRecordBase.FindAll(typeof(Entity));
}
public new static Entity Find(int id)
{
return (Entity)ActiveRecordBase.FindByPrimaryKey(typeof(Entity), id);
}
}
[ActiveRecord("EntityCompany")]
public class CompanyEntity : Entity
{
private byte company_type;
private int comp_id;
[JoinedKey("comp_id")]
public int CompId
{
get { return comp_id; }
set { comp_id = value; }
}
[Property("company_type")]
public byte CompanyType
{
get { return company_type; }
set { company_type = value; }
}
public new static void DeleteAll()
{
ActiveRecordBase.DeleteAll(typeof(CompanyEntity));
}
public new static CompanyEntity[] FindAll()
{
return (CompanyEntity[])ActiveRecordBase.FindAll(typeof(CompanyEntity));
}
public new static CompanyEntity Find(int id)
{
return (CompanyEntity)ActiveRecordBase.FindByPrimaryKey(typeof(CompanyEntity), id);
}
}
[ActiveRecord("EntityPerson")]
public class PersonEntity : Entity
{
private int person_id;
[JoinedKey("person_id")]
public int PersonId
{
get { return person_id; }
set { person_id = value; }
}
public new static void DeleteAll()
{
ActiveRecordBase.DeleteAll(typeof(PersonEntity));
}
public new static PersonEntity[] FindAll()
{
return (PersonEntity[])ActiveRecordBase.FindAll(typeof(PersonEntity));
}
public new static PersonEntity Find(int id)
{
return (PersonEntity)ActiveRecordBase.FindByPrimaryKey(typeof(PersonEntity), id);
}
}


这个例子中,首先在基类Entity的属性标签加上"JoinedBase"参数(表示为一个或多个subclass的父类),然后在子类CompanyEntity和PersonEntity中分别增加一个属性CompId和PersonId并打上"JoinedKey"属性标签(它们在数据表中体现为外键,通过它把子类与基类的表关联起来)。
这种方法会将基类映射到一张数据表,子类分别映射到单独的一张数据表(表里不包含基类的属性值,这些值都在基类映射的数据表中)。持久化子类的时候,相关信息分别保存到基类和子类映射的数据表中。

测试一下:


private void TestSubclass()
{
PersonEntity person = new PersonEntity();
person.Id = 500;
person.Name = "Allen";
person.Create();
CompanyEntity company = new CompanyEntity();
company.Id = 100;
company.Name = "SomeName";
company.Create();
Entity en = Entity.Find(100);
string str = en.ToString() + ", ID=" + en.Id + ", Name=" + en.Name;
CompanyEntity comp = CompanyEntity.Find(100);
str += "\r\n" + comp.ToString() + ", ID=" + comp.Id.ToString() + ", CompId=" + comp.CompId.ToString() + ", Name=" + comp.Name;
PersonEntity pers = PersonEntity.Find(500);
str += "\r\n" + pers.ToString() + ", ID=" + pers.Id.ToString() + ", PersonId=" + pers.PersonId.ToString() + ", Name=" + pers.Name;
MessageBox.Show(str);
}

显示结果:
xx.CompanyEntity, ID=100, Name=SomeName
xx.CompanyEntity, ID=100, CompId=0, Name=SomeName
xx.PersonEntity, ID=500, PersonId=0, Name=Allen

这里很奇怪的是 CompId和PersonId 应该和 ID 是相同的值,但取出来却都是0。 不知道是为什么...


二、使用 Discriminator


[ActiveRecord("EntityBase", DiscriminatorColumn = "type", DiscriminatorType = "String", DiscriminatorValue="Entity")]
public abstract class EntityBase : ActiveRecordBase<EntityBase>
{
private int _id;
private string _name;
public EntityBase()
{
}
public EntityBase(string name)
{
this._name = name;
}
[PrimaryKey(PrimaryKeyType.Native, "id")]
public int ID
{
get { return _id; }
set { _id = value; }
}
[Property("name")]
public string Name
{
get { return _name; }
set { _name = value; }
}
}
[ActiveRecord(DiscriminatorValue = "blog")]
public class BlogEntity : EntityBase
{
private IList _posts;
public BlogEntity()
{
this._posts = new ArrayList();
}
public BlogEntity(string name) : base(name)
{
}
[HasMany(typeof(PostEntity), Table = "Entity", ColumnKey = "post_of", Cascade = ManyRelationCascadeEnum.All)]
public IList Posts
{
get { return _posts; }
set { _posts = value; }
}
public new static void DeleteAll()
{
ActiveRecordBase<BlogEntity>.DeleteAll();
}
public new static BlogEntity[] FindAll()
{
return ActiveRecordBase<BlogEntity>.FindAll();
}
public static BlogEntity Find(int id)
{
return ActiveRecordBase<BlogEntity>.Find(id);
}
public static BlogEntity TryFind(int id)
{
return ActiveRecordBase<BlogEntity>.TryFind(id);
}
}
[ActiveRecord(DiscriminatorValue = "post")]
public class PostEntity : EntityBase
{
private BlogEntity _blog;
public PostEntity()
{
}
public PostEntity(string name) : base(name)
{
}
[BelongsTo("post_of")]
public BlogEntity Blog
{
get { return _blog; }
set { _blog = value; }
}
public new static void DeleteAll()
{
ActiveRecordBase<PostEntity>.DeleteAll();
}
public new static PostEntity[] FindAll()
{
return ActiveRecordBase<PostEntity>.FindAll();
}
public static PostEntity Find(int id)
{
return ActiveRecordBase<PostEntity>.Find(id);
}
public static PostEntity TryFind(int id)
{
return ActiveRecordBase<PostEntity>.TryFind(id);
}
}

这种方法会将所有的信息都映射到一个数据表中,通过鉴别器的值DiscriminatorValue来区分各个类的实例(数据表中的一条记录)。

运行下面的代码:


private void TestDiscriminator()
{
for (int i = 1; i < 6; i++)
{
BlogEntity blog = new BlogEntity("blog-" + i.ToString());
blog.Create();
}
PostEntity post1 = new PostEntity("post_01");
PostEntity post2 = new PostEntity("post_02");
using (TransactionScope tran = new TransactionScope())
{
try
{
BlogEntity blog2 = BlogEntity.Find(2);
blog2.Name = "Dotnet Fantasy";
blog2.Posts.Add(post1);
blog2.Posts.Add(post2);
blog2.Save();
tran.VoteCommit();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace);
tran.VoteRollBack();
}
}
}

执行后数据库中EntityBase表的记录:
id  type    name     post_of          
1   blog   blog-1     NULL          
2   blog   Dotnet Fantasy   NULL
3   blog   blog-3     NULL          
4   blog   blog-4     NULL          
5   blog   blog-5     NULL          
6   post   post_01   2                  
7   post   post_02   2                  

 

结论:
  其实,这两种实现方法用“层”的概念来描述更贴切一些。
  至于用什么方式来实现所需要的继承,可以按需求来选择(当然不会仅限于这两种方法)。
  另外,不知道在NHibernate里处理继承关系是不是会更加灵活呢?


[导入]Castle ActiveRecord学习记录 - 处理继承关系
文章来源:http://www.agilelabs.cn/blogs/%e8%8c%83%e4%bf%8a/archive/2006/05/16/1216.aspx

转载于:https://www.cnblogs.com/debug1/archive/2006/05/16/413757.html

上一篇:关于sql连接语句中的Integrated Security=SSPI


下一篇:vs code 中配置git go