Castle ActiveRecord学习实践(3):映射基础

摘要:本文详细介绍了ActiveRecord中的基本映射,对于关联映射会在后续文章中通过一些具体的实例来说明。

主要内容

简单映射

1ActiveRecordAttribute

2. PrimaryKeyAttribute

3CompositeKeyAttribute

4PropertyAttribute

5FieldAttribute

 

一.ActiveRecordAttribute

每一个实体类都必须继承于基类ActiveRecordBase,并在实体类上设置特性ActiveRecordAttribute,示例代码

//指定数据库表名

[ActiveRecord(
"Blogs")]

public class Blog : ActiveRecordBase

{

    
//

}


//不指定数据库表名

[ActiveRecord]

public class Blog : ActiveRecordBase

{

    
//

}

 

 ActiveRecordAttribute说明

属性

说明

示例

Table

指定持久化类所对应的数据库表名,如果表名与类名相同,可以省略

[ActiveRecord("Blogs")]

[ActiveRecord(Table="Blogs")]

 

Schema

指定Schema的名字

Schema="ARDemo"

Proxy

指定一个接口,在延迟装载时作为代理使用

 

DiscriminatorColumn

识别器的字段名

DiscriminatorColumn="Blog"

DiscriminatorType

识别器的字段类型

DiscriminatorType="String"

DiscriminatorValue

识别器字段的值

 

Where

指定一个附加SQLWhere子句

Where="IsPost = 0"

Lazy

指定是否延迟加载

Lazy=true|false

 

二.PrimaryKeyAttribute

在实体类中,通过PrimaryKeyAttribute来指定表的主键,示例代码

//指定主键字段名

[ActiveRecord()]

public class Blog : ActiveRecordBase

{

    
private int id;

 

    [PrimaryKey(
"blog_id")]

    
public int Id

    
{

        
get return id; }

        
set { id = value; }

    }


}


//不指定主键字段名

[ActiveRecord()]

public class Blog : ActiveRecordBase

{

    
private int id;

 

    [PrimaryKey]

    
public int Id

    
{

        
get return id; }

        
set { id = value; }

    }


}


PrimaryKeyAttribute说明

属性

说明

示例

PrimaryKeyType

主键生成的方式,如果不指定,则默认的方式为PrimaryKeyType.Native

PrimaryKeyType.Native

Column

主键字段名称,如果跟属性名相同,可以不用指定

PrimaryKey("blog_id")

ColumnType

主键字段的类型

 

Generator

是一个.NET类的名字,用来为该持久化类的实例生成唯一的标识。

 

Params

Params来提供Generator所需要的配置参数或初始化参数

 

Length

主键字段的长度

Length=10

SequenceName

当指定主键的生成方式为Sequence时,序列的名称

PrimaryKey(PrimaryKeyType.Sequence, SequenceName="myseqname")

UnsavedValue

用来标志该实例是刚刚创建的,尚未保存。

 

 

主键的生成方式介绍

名称

说明

Identity

DB2,MySQL, MS SQL Server, SybaseHypersonicSQL的内置标识字段提供支持,生成自增的整型

Sequence

序列,对DB2,MySQL, PostgreSQL, Oracle的内置标识字段提供支持,生成自增的整型。

HiLo

高低位,使用一个高/低位算法来高效的生成Int64, Int32 或者 Int16类型的标识符。

SeqHiLo

使用序列的高低位,使用一个高/低位算法来高效的生成Int64, Int32 或者 Int16类型的标识符,给定一个数据库序列(sequence)的名字。

UuidHex

用一个System.Guid和它的ToString(string format)方法生成字符串类型的标识符。

UuidString

用一个新的System.Guid产生一个byte[] ,把它转换成字符串。

Guid

用一个新的System.Guid 作为标识符。

GuidComb

Jimmy Nilsso的一个算法产生一个新的System.Guid

Native

根据底层数据库的能力选择 identity, sequence 或者 hilo中的一个。默认值。

Assigned

让应用程序在自己为对象分配一个标示符。

Foreign

使用另外一个相关联的对象的标识符。

 

三.CompositeKeyAttribute

如果使用组合键,需要我们自定义一个类来作为主键属性的类型。示例代码

[PrimaryKey]

public MyCompositeKey ID

{

    
get return _key; }

    
set { _key = value; }

}


对于组合键类,除了需要加上CompositeKey特性之外,它还需要是可序列化的,并且要求实现EqualsGetHashCode方法。ActiveRecord官方网站上提供的一个组合键的示例程序如下:

[CompositeKey, Serializable]

public class MyCompositeKey

{

    
private string _keyA;

    
private string _keyB;

 

    [KeyProperty]

    
public virtual string KeyA

    
{

        
get return _keyA; }

        
set { _keyA = value; }

    }


 

    [KeyProperty]

    
public virtual string KeyB

    
{

        
get return _keyB; }

        
set { _keyB = value; }

    }


 

    
public override string ToString()

    
{

        
return string.Join( ":"new string[] { _keyA, _keyB } );

    }


 

    
public override bool Equals( object obj )

    
{

        
if( obj == this ) return true;

        
if( obj == null || obj.GetType() != this.GetType() ) return false;

        MyCompositeKey test 
= ( MyCompositeKey ) obj;

        
return ( _keyA == test.KeyA || (_keyA != null && _keyA.Equals( test.KeyA ) ) ) &&

            ( _keyB 
== test.KeyB || ( _keyB != null && _keyB.Equals( test.KeyB ) ) );

    }


 

    
public override int GetHashCode()

    
{

        
return _keyA.GetHashCode() ^ _keyB.GetHashCode();

    }


}

 

四.PropertyAttribute

ActiveRecord中通过PropertyAttribute来指定实体类属性与数据库中的字段映射。

[ActiveRecord()]

public class Blog : ActiveRecordBase

{

    
//不指定字段名

    [Property]

    
public int Name

    
{

        
get return _name; }

        
set { _name = value; }

    }


}


 

[ActiveRecord()]

public class Blog : ActiveRecordBase

{

    
//指定字段名

    [Property(
"blog_name")]

    
public int Name

    
{

        
get return _name; }

        
set { _name = value; }

    }


}


PropertyAttribute说明

属性

说明

示例

Column

对应的数据库字段名

Property("blog_name")

ColumnType

对应的字段类型

 

Formula

一个SQL表达式,定义了这个计算(computed) 属性的值。计算属性没有和它对应的数据库字段。

 

UnsavedValue

用来标志该实例是刚刚创建的,尚未保存。

 

Length

字段的长度

Length=10

NotNull

是否可以为空

NotNull=true|false

Unique

是否允许重复

Unique=true|false

Update

表明在用于UPDATE SQL语句中是否包含这个字段。默认为true

Update=true|false

Insert

表明在用于INSERTSQL语句中是否包含这个字段。默认为true

Insert=true|false

 

五.FieldAttribute

ActiveRecord中,允许我们直接对Field进行映射,使用FieldAttribute

[ActiveRecord()]

public class Blog : ActiveRecordBase

{

    
//不指定字段名称

    [Field]

    
string _name;

}


 

[ActiveRecord()]

public class Blog : ActiveRecordBase

{

    
//指定字段名称

    [Field(
"blog_name")]

    
string _name;

}


FieldAttribute说明

属性

说明

示例

Column

对应的数据库字段名

Property("blog_name")

ColumnType

对应的字段类型

 

Formula

一个SQL表达式,定义了这个计算(computed) 属性的值。计算属性没有和它对应的数据库字段。

 

UnsavedValue

用来标志该实例是刚刚创建的,尚未保存。

 

Length

字段的长度

Length=10

NotNull

是否可以为空

NotNull=true|false

Unique

是否允许重复

Unique=true|false

Update

表明在用于UPDATE SQL语句中是否包含这个字段。默认为true

Update=true|false

Insert

表明在用于INSERTSQL语句中是否包含这个字段。默认为true

Insert=true|false

 

六.NestedAttribute

在映射的时候我们也可以用子对象来映射数据库中的字段,示例代码

[ActiveRecord]

public class Company : ActiveRecordBase

{

    
private PostalAddress _address;

 

    [Nested]

    
public PostalAddress Address

    
{

        
get return _address; }

        
set { _address = value; }

    }


}


 

public class PostalAddress

{

    
private String _address;

    
private String _city;

    
private String _state;

    
private String _zipcode;

 

    
public PostalAddress()

    
{

    }


 

    
public PostalAddress(String address, String city,

        String state, String zipcode)

    
{

        _address 
= address;

        _city 
= city;

        _state 
= state;

        _zipcode 
= zipcode;

    }


 

    [Property]

    
public String Address

    
{

        
get return _address; }

        
set { _address = value; }

    }


 

    [Property]

    
public String City

    
{

        
get return _city; }

        
set { _city = value;}

    }


 

    [Property]

    
public String State

    
{

        
get return _state; }

        
set { _state = value; }

    }


 

    [Property]

    
public String ZipCode

    
{

        
get return _zipcode; }

        
set { _zipcode = value; }

    }


}

 

NestedAttribute说明

属性

说明

示例

Update

表明在用于UPDATE SQL语句中是否包含这个字段。默认为true

Update=true|false

Insert

表明在用于INSERTSQL语句中是否包含这个字段。默认为true

Insert=true|false

基本的映射就介绍这么多了,剩下的还有版本(VersionAttribute),时间戳(TimestampAttribute)等映射大家可以参考相关的文档。在下篇文章中我会通过一个具体的实例介绍实现One-Many/Many-One映射。

 

参考资料

Castle的官方网站http://www.castleproject.org

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2006-04-06 08:28 TerryLee 阅读(12220) 评论(31)  编辑 收藏 网摘 所属分类: [11]  数据持久[12]  开源世界

  回复  引用  查看    
#1楼2006-04-06 10:32 | windwolf      
看起来就是把nh的映射文件属性化了
nested的概念是否就是nh里的one2one的概念?

  回复  引用  查看    
#2楼[楼主]2006-04-06 11:35 | Terrylee      
@windwolf
ActiveRecord就是利用特性来代替了NH中的映射文件

nested并不是one2one的概念,它是对应的同一实体类,只不同通过一些子对象来实现映射。

one2one对应的是不同的实体类,通过OneToOneAttribute来实现。

  回复  引用    
#3楼2006-06-01 10:05 | wujun[未注册用户]
我用了你有User这个类的一个例子,发现在执行user.Create();程序报错信息“could not perform save for user”,不知道什么原因,我是第一次用ActiveRecord。
  回复  引用  查看    
#4楼[楼主]2006-06-01 11:04 | TerryLee      
@wujun

1.看User有没有继承与ActiveRecordBase,并且在类上使用特性[ActiveRecord]

2.看有没有初始化
ActiveRecordStarter.Initialize( source, typeof(User) );

  回复  引用    
#5楼2006-06-05 17:16 | 初学ActiveRecord[未注册用户]
@TerryLee

Could not perform Save for BlogCastle.ActiveRecord
有Blog这个类
初始化方法:
void Application_Start(object sender, EventArgs e)
{
IConfigurationSource source = System.Configuration.ConfigurationManager.GetSection("activerecord") as IConfigurationSource;

Type[] paramTypes = new Type[3];
paramTypes[0] = typeof(User1);
paramTypes[1] = typeof(Post);
paramTypes[2] = typeof(Blog);
ActiveRecordStarter.Initialize(source, paramTypes);
// IConfigurationSource source = System.Configuration.ConfigurationManager.GetSection("activerecord") as IConfigurationSource;
// 在应用程序启动时运行的代码

}

  回复  引用  查看    
#6楼[楼主]2006-06-05 17:34 | TerryLee      
@初学ActiveRecord
你是不是用的是.NET2.0?

  回复  引用  查看    
#7楼[楼主]2006-06-05 17:34 | TerryLee      
@初学ActiveRecord
你是不是用的是.NET2.0?

看一下AR的版本是否正确?

  回复  引用    
#8楼2006-06-05 17:59 | 初学ActiveRecord[未注册用户]
是用的2.0啊,AR版本也是2.0的啊
  回复  引用  查看    
#9楼[楼主]2006-06-05 18:19 | TerryLee      
@初学ActiveRecord
这个错误我这儿没有出现

现在在不能浮现这个错误,我不太清楚是哪儿出错了:)

  回复  引用    
#10楼2006-06-11 12:02 | 旺旺2006[未注册用户]
@初学ActiveRecord
这个错误我出现过 ConnectionString 错了

  回复  引用  查看    
#11楼[楼主]2006-06-21 16:54 | TerryLee      
@一汐
<add assembly="*"/>是哪儿的?

  回复  引用  查看    
#12楼2006-07-14 16:50 | 风平浪静      
@初学ActiveRecord
看看你的实体类是否与数据库中的字段是否对应好:)

  回复  引用    
#13楼2006-07-30 12:57 | microshot[未注册用户]
@TerryLee
请问组合键的Property如何写?比如用了两个键进行组合
private int _blogId;
private int _communityId;

[PrimaryKey(PrimaryKeyType.Native, "blog_Id")]
public int BlogId
{
get
{
return this._blogId;
}
set
{
this._blogId = value;
}
}

[PrimaryKey(PrimaryKeyType.Native, "community_Id")]
public int CommunityId
{
get
{
return this._communityId;
}
set
{
this._communityId = value;
}
}


是不是把这两个属性写在自定义的类里面,那么在原来表对应的类里面不在出现,而加入:
[PrimaryKey]
public MyCompositeKey ID
{
get { return _key; }
set { _key = value; }
}

这样写法可以吗?

  回复  引用    
#14楼2006-07-30 13:09 | microshot[未注册用户]
@TerryLee
另外新建的类需要继承ActiveRecordBase并在开始Initialize吗?
需要对他进行对应表和字段吗

  回复  引用  查看    
#15楼[楼主]2006-07-30 13:31 | TerryLee      
@microshot

参见上面的三.CompositeKeyAttribute

不需要继承ActiveRecordBase,但是它应该是可序列化的

  回复  引用    
#16楼2006-07-30 13:36 | microshot[未注册用户]
@TerryLee

定义了类myBcKey,并在原来的类中定义了这个类,
编译通过,运行在Initialize()时直接出现
To use type 'myBcKey' as a composite id it must have two or more properties marked with the [KeyProperty] attribute.

  回复  引用    
#17楼2006-07-30 13:45 | microshot[未注册用户]
@TerryLee
OK了,必须要用KeyProperty:)

  回复  引用  查看    
#18楼[楼主]2006-07-30 14:01 | TerryLee      
@microshot
-_-

  回复  引用  查看    
#19楼2006-08-23 09:30 | microshot      
@TerryLee
A,B 两张表 一对多的关系,其中B的外键是B的联合主键的其中一个,这个关系怎么配置呢?

  回复  引用  查看    
#20楼2006-10-25 11:55 | 阿武      
你好, TerryLee ,非常感谢你这一系统的文章,对我帮助很大.我有一个问题想请教一下,
为什么我我设置了DiscriminatorColumn,DiscriminatorType,DiscriminatorValue 但 FindAll还是把所有数据都获取所有了呢
我的设置如下:
DiscriminatorColumn = "TypeId",
DiscriminatorType = "System.Int32",
DiscriminatorValue = "1"

在 .net 1.1 和 2.0 下测试了都一样

  回复  引用  查看    
#21楼[楼主]2006-10-25 13:19 | TerryLee      
@阿武
识别器没测试过,你可以使用Where子句来实现啊

  回复  引用  查看    
#22楼2006-10-25 14:10 | 阿武      
@TerryLee
谢谢,我也想到用 Where 来代替,但暂时还没想到两者之间在使用上有什么区别, 或者说 Discriminator 本来就可以当成是 Where 是子一个子集,不知道这样理解有没有问题

  回复  引用  查看    
#23楼2006-10-25 15:10 | 阿武      
刚刚测试了一下,如果添加了Discriminator,那么在添加修改操作TypeId的值就不需要设置了,看来还是跟Where子句配合使用,不知道其它人是不是也是这样处理的
  回复  引用  查看    
#24楼[楼主]2006-10-25 22:59 | TerryLee      
@阿武
用Where子句完全就可以了,一直都没用过Discriminator

  回复  引用    
#25楼2006-12-24 01:04 | row[未注册用户]
hi terrylee我的偶像,我今天才开始看的castle,我有个问题想请教

public class Blog : ActiveRecordBase

如上 业务实体都继承自ActiveRecordBase 它是个接口还是个类啊

如果是个类,我想请问

如果我有一个Account类 一个MoneyAccount类

MoneyAccount类很多属性都是继承自Account的

我如何处理这个问题

class Account
{
private string name;
public string Name
{
get{return name;}
set{name=value;}
}
}
class MoneyAccount:Account(我是想这样.C#不是只能继承自1个类吗?那现在怎么解决)
{
}



  回复  引用    
#26楼2006-12-24 01:07 | row[未注册用户]
老天保佑你会很快发现我的留言

保佑

谢谢了

  回复  引用    
#27楼2006-12-24 01:49 | row[未注册用户]
以解决 谢谢
  回复  引用  查看    
#28楼[楼主]2006-12-24 15:55 | TerryLee      
@row
不好意思,上午参加培训去了,刚看到

解决了就好,其实AR是支持这个的

有没有试过在Nest 类中定义 :BeLongTo标记,这个不行,不知道是Bug还是有其它设置 方法?
  回复  引用  查看    
#30楼2008-05-22 17:23 | ζ浮云¢惊龙      
非常感谢
  回复  引用    
#31楼2009-05-04 22:13 | 没钱买烟啦
求助,我用castle查询14万条数据,其中包含该条件的数据有10万条,查询结果用了一分多钟,请问一下,通过castle查询大量数据时,一般使用何种方式?



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 367978




相关文章:

相关链接: