DBO ( database object ) 使用手册
概述
代码霹雳啪啦写好了,要写文档了,感觉真的很难,无从下手。废话就不说了,进入正题。
DBO—database object operation toolkit . 说白了,又一个轮子—OR Mapping工具。 在.net领域,这种轮子已经很多了:NHinerate,IBaitc.net,NBear等等。 轮子是圆的,但并不意味着十全十美。
之所以写DBO,源于几年来的设计习惯:我们利用面向对象的语言,嚷着要进行面向对象的设计,但企业程序设计中,三层的架构,真正按完全的面向对象设计来构建的有几个?
这是笔者习惯的设计方法:
三层结构:表现层,业务层,数据访问层,各层之间通过实体对象传递数据,实体对象跟数据库表结构基本一致,实体之间不会存在对象关联,而是通过ID关联(这应该不是一个面向对象的方法吧)。
功能强大的OR Mapping工具都支持关联表操作,关联表操作又会引起另外的问题:关联加载时的性能问题,于是,为解决这个问题,又提供了Lazy-load特性,这个特性实现的如何,暂不作评论。
数据库是平板数据的关联,我们的表现层页面,大多数情况下也是平板的(表格)。而对象,对象的关系却是一个树和网的关系。
笔者的设计观点:
三层架够的开发中,让面向对象见鬼去吧,我们还是采用平板数据。(当然不是贬低面向对象,DBO的的确确是用面向对象的思想开发出来的).
DBO核心功能
1. 利用特性(Attribute)配置实体映射信息。
2. 单表实体操作:实现对单个实体,单个表的增删改查。
3. 关联删除:可以一次将多级关联的实体删除。
4. 条件操作:按照强类型查询条件,进行单个实体,单个表的增删改查。查询条件支持任意拼凑。
5. 跨表查询支持:利用关联实体实现跨表查询,支持设置join方式。
6. 强类型查询语句:利用C#代码写sql.。(有点鸡肋,大家看看啦)。
记住一点:DBO中没有直接的对象关联,所有的对象关系通过特性指定。
没有了直接的对象关联,所有的实体类成了平板数据,避免了lazy-load,和由lazy-load引起的其它问题。
DBO的基本接口
基本会话接口
/// 基本实体操作
/// base operation to dbo
/// </summary>
public interface IDboBaseSession
{
/// <summary>
/// 按照主键获取一个实体
/// get a entity from database by primary key
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="keys"></param>
/// <returns></returns>
T Get<T>(object keys) where T : class, new();
/// <summary>
/// 按照主键获取一个实体,支持多个主键
/// load a entity , suport many primary keys
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
bool Load<T>(T obj) where T : class, new();
/// <summary>
/// 插入一个实体
/// insert a entity to database
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <returns></returns>
int Insert<T>(T o) where T : class, new();
/// <summary>
/// 修改一个实体
/// update a entity to database
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <returns></returns>
int Update<T>(T o) where T : class, new();
/// <summary>
/// 删除一个实体
/// delete a entity from database
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <returns></returns>
int Delete<T>(T o) where T : class, new();
//int Delete<T>(T o, bool deleteRef) where T : class, new();
/// <summary>
/// 删除所有实体
/// delete all entity from the table
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
int DeleteAll<T>() where T : class, new();
//int Delete(Type t, object keyValue, bool delRef);
/// <summary>
/// 保存一个实体,插入或修改
/// insert or update a entity to the database
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <returns></returns>
int Save<T>(T o) where T : class, new();
/// <summary>
/// 获取所有实体
/// load all entities from a table
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
IList<T> LoadAll<T>() where T : class, new();
}
条件会话接口
/// 条件操作
/// operation with query to dbo
/// </summary>
public interface IDboConditionSession //: ICloseRequire
{
/// <summary>
/// 按照条件获取一个实体
/// get a entity with the conditon
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="q"></param>
/// <returns></returns>
T Get<T>(ConditionExpression q) where T : class, new();
/// <summary>
/// 按照条件修改实体
/// update a entity with the condition
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <param name="q"></param>
/// <returns></returns>
int Update<T>(T o, ConditionExpression q) where T : class, new();
/// <summary>
/// 按照条件修改实体的某些字段
/// update a entity with the condition and only update the special fields
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <param name="q"></param>
/// <param name="fields"></param>
/// <returns></returns>
int Update<T>(T o, ConditionExpression q, params IQueryField[] fields ) where T : class, new();
/// <summary>
/// 按照条件删除实体
/// delete entities with the contidition
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="q"></param>
/// <returns></returns>
int Delete<T>(ConditionExpression q) where T : class, new();
/// <summary>
/// 按照条件查询实体列表
/// query list of a entity with the condition
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="q"></param>
/// <returns></returns>
IList<T> Query<T>(ConditionExpression q) where T : class, new();
/// <summary>
/// 按照条件查询实体表格
/// query a table of a entity with the condition
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="q"></param>
/// <returns></returns>
DataTable QueryTable<T>(ConditionExpression q) where T : class, new();
/// <summary>
/// 按照条件查询关联实体列表
/// query a joined entity whth the condition
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="q"></param>
/// <returns></returns>
IList<T> JoinQuery<T>(ConditionExpression q) where T : class, new();
/// <summary>
/// 按照强类型sql语句查询实体列表
/// query list of a entity with a strong type sql
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="q"></param>
/// <returns></returns>
IList<T> Query<T>(QueryExpression q) where T : class, new();
/// <summary>
/// 按照强类型sql语句查询DataSet
/// query dataSet of a entity with a strong type sql
/// </summary>
/// <param name="qs"></param>
/// <returns></returns>
DataSet QueryDataSet(params QueryExpression[] qs); //where T : class, new();
}
关系操作接口
/// <summary>
/// 关系操作
/// relatin operation to dbo , for the many to many relation
/// </summary>
public interface IDboRelationSession
{
/// <summary>
/// 删除实体,可以指定是否进行关联删除(删除所有自实体)
/// delete the reference of the two entities
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <param name="deleteRef"></param>
/// <returns></returns>
int Delete<T>(T o, bool deleteRef) where T : class, new();
/// <summary>
/// 获取父实体
/// get parent entity of a entity
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
T GetRef<T>(object obj) where T : class, new();
/// <summary>
/// 获取子实体列表
/// get children entities of a entity
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
IList<T> GetRefList<T>(object obj) where T : class, new();
/// <summary>
/// 保存多对多实体关系
/// save the reference of the two entities
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
int SaveRef(object obj1, object obj2);
/// <summary>
/// 删除多对多实体关系
/// delete the reference of the two entities
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
int DeleteRef(object obj1, object obj2);
}
/// 关系操作
/// relatin operation to dbo , for the many to many relation
/// </summary>
public interface IDboRelationSession
{
/// <summary>
/// 删除实体,可以指定是否进行关联删除(删除所有自实体)
/// delete the reference of the two entities
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <param name="deleteRef"></param>
/// <returns></returns>
int Delete<T>(T o, bool deleteRef) where T : class, new();
/// <summary>
/// 获取父实体
/// get parent entity of a entity
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
T GetRef<T>(object obj) where T : class, new();
/// <summary>
/// 获取子实体列表
/// get children entities of a entity
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
IList<T> GetRefList<T>(object obj) where T : class, new();
/// <summary>
/// 保存多对多实体关系
/// save the reference of the two entities
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
int SaveRef(object obj1, object obj2);
/// <summary>
/// 删除多对多实体关系
/// delete the reference of the two entities
/// </summary>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
int DeleteRef(object obj1, object obj2);
}
开始使用DBO
第一步:设计数据库
按照我们的习惯设计数据库,建议使用PowerDesigner功能,利用它的代码生成功能生成实体代码。也可以用其他工具,如CodeSmith。再强调一下:DBO支持的实体是平板数据,实体类属性跟数据表属性一一对应。
如,有一个组织机构类:
using DBO.Attributes;
using DBO.QueryLanguage;
using DBO.QueryLanguage.SpecalField;
[Table("Org")]
[Relation(typeof(User), RelationMode.OneToMany )]
class Org
{
static public QueryField<Org> __OrgId = new QueryField<Org>("OrgId"); //查询字段
static public StringQueryField<Org> __OrgName = new StringQueryField<Org>("OrgName");
static public IntQueryField<Org> __ParentId = new IntQueryField<Org>("ParentId");
private int _OrgId;
[PrimaryKey( KeyGenerateMode.Guid )]
public int OrgId
{
get { return _OrgId; }
set { _OrgId = value; }
}
private string _OrgName;
[Column(Name="OrgName")]
public string OrgName
{
get { return _OrgName; }
set { _OrgName = value; }
}
private string _Location = "l";
public string Location
{
get { return _Location; }
set { _Location = value; }
}
private int? _ParentId;
public int? ParentId //支持nullable
{
get { return _ParentId; }
set { _ParentId = value; }
}
private DateTime _CreateTime = DateTime.Now ;
public DateTime CreateTime
{
get { return _CreateTime; }
set { _CreateTime = value; }
}
private int _ObjectState = 0;
[NoMap]
public int ObjectState
{
get { return _ObjectState; }
set { _ObjectState = value; }
}
}
从以上类我们可以了解到以下用来配置影射的特性(Attribute):
Table :指定实体类映射到的表名,若没指定则表名跟类名一致。
Relation:指定跟其他实体的关系,支持 OneToOne , OneToMany ,ManyToOne ,ManyToMany。
PrimaryKey : 指定主键字段,支持多个主键,主键生成,模式支持标识,Sequence,Guid,None。
Column: 配置映射到的列,若无,则列名跟属性名一致。
NoMap:指定此属性不参与映射。
Ref:指定此属性关联到的实体(以上Org类没有体现出来,可以看下面的User类)。
那些 static public QueryField<Org> 是什么呢?
QueryField : 这个静态字段写上去之后,就可以按某个字段任意查询了!
第二步:设置连接字符串
数据库连接的配置采用.net2.0中标准的配置:
<connectionStrings>
<add name="default" connectionString="data source=(local);packet size=4096;user id=sa;initial catalog=DboExapmle;password=123456" providerName="System.Data.SqlClient" />
</connectionStrings>
第三步:写调用代码啦
using DBO;using DBO.QueryLanguage;
IDboSession dboSession = DboFactory.OpenDboSession("defalut"); //打开数据库会话
Org org = new Org();
org.OrgName = "Org1";
dboSession.Insert(org); //插入
dboSession.Delete(org); //再删除
dboSession.Update(org); //修改
Org orgFormDb = dboSession.Get<Org>( 1 ); //按照主键获取一个实体
Org orgFromDb2 = dboSession.Get<Org>(Org.__OrgName == "Org1"); //按条件获取获取一个实体
IList<Org> orgs = dboSession.Query<Org>(Org.__OrgName == "Org1" | Org.__OrgName == "Org2"); //按条件查询
IList<Org> allOrgs = dboSession.LoadAll<Org>(); //加载所有数据
dboSession.DeleteAll<Org>(); //清空表
dboSession.Close(); //关闭数据库会话
DBO高级功能
跨表查询
假设有两个表:部门表 Org 和用户表 User,Org实体如上,User 实体如下:
using DBO.Attributes;
using DBO.QueryLanguage;
using DBO.QueryLanguage.SpecalField;
[Table("User")]
class User
{
static public StringQueryField<User> __UserName = new StringQueryField<User>("UserName");
static public QueryField<User> __OrgId = new QueryField<User>("OrgId");
static public TypeQueryField<User, UserType> __UserType = new TypeQueryField<User, UserType>("UserType");
static public TypeQueryField<User, int> __Age = new TypeQueryField<User, int>("Age");
private int _UserId;
[PrimaryKey]
public int UserId
{
get { return _UserId; }
set { _UserId = value; }
}
private string _UserName;
public string UserName
{
get { return _UserName; }
set { _UserName = value; }
}
private int _Age;
public int Age
{
get { return _Age; }
set { _Age = value; }
}
private int _OrgId;
[Ref(typeof(Org))]
public int OrgId
{
get { return _OrgId; }
set { _OrgId = value; }
}
}
现在有一个页面,需要显示一个用户列表,同时显示出每个用户所属的部门名。可以建一个关联实体:
[Join( typeof(Org) , JoinMode.LeftJoin )] //设置关联信息
class RefOrgUser : User
{
private string _OrgName;
[Column(Owner = typeof(Org), DisplayName = "单位名" , DataType=DataType.LargText,MaxLength=50)]
public string OrgName
{
get { return _OrgName; }
set { _OrgName = value; }
}
}
OK,RefOrgUser对象拥有了OrgName属性,可以满足页面显示的需要了:
using DBO.QueryLanguage;
IDboSession dboSession = DboFactory.OpenDboSession("defalut"); //打开数据库会话
IList<RefOrgUser> usersWithOrg = dboSession.Query<RefOrgUser>(Org.__OrgId == 1); //获取部门Id为1的所有用户
Sql随意查询
using DBO;using DBO.QueryLanguage;
QueryExpression expr =
DboQuery.Select( User.__UserName,Org.__OrgName )
.From<User>()
.InnerJoin<Org>().On(User.__OrgId, Org.__OrgId)
.Where(Org.__OrgId == 2 | Org.__OrgId == 3);
IList<RefOrgUser> orgs = _session.Query<RefOrgUser>(expr) ;
关联删除
删除单位1和单位1下所有用户
using DBO.QueryLanguage;
IDboSession dboSession = DboFactory.OpenDboSession("defalut"); //打开数据库会话
Org deletedOrg = new Org();
deletedOrg.OrgId = 1;
dboSession.Delete(deletedOrg, true);
jianyi0115@163.com
于