zhuweisky

君子之行,静以修身,俭以养德。非淡泊无以明志,非宁静无以致远。
ESFramework,基于.NET的通信框架。DataRabbit,轻量的数据访问框架。DCFramework,基于.NET的动态分布式计算框架。sky.zhuwei@163.com

统计

留言簿

积分与排名

好友博客

阅读排行榜

评论排行榜

DataRabbit 轻量的数据访问框架(02) -- IOrmAccesser

   (完全限定类名:DataRabbit.ORM.IOrmAccesser)   

   在DataRabbit框架中,通过IOrmAccesser来对数据库进行ORM访问,只要Entity(即ORM中的“O”)的定义与数据库表的结构完全一致,即可使用IOrmAccesser来对其进行ORM操作。

1.Entity
   Entity除了包括成员变量与属性(这些变量与属性与数据库表的结构完全一致)外,不需要包含任何其它元素。在轻量的数据访问框架 --序 的例子代码中,我们已经看到了一个Student Entity的示例。

2.Filter
   我们经常需要依据条件来搜索数据,在DataRabbit的ORM框架中,使用Filter来表示一个单独的条件。Filter从ColumnItem继承,ColumnItem 表示数据列及其对应的值。比如,在进行Update操作时,我们可以使用一个ColumnItem 的List来指定要将哪些列的值更新为指定的值。

   首先,注意,Filter中包含一个GetBooleanExpression()方法,该方法将当前Filter转换为一个标准的Sql条件字句。
   Filter的ComparisonOperator属性表明了采用何种比较符来构建条件表达式。
ComparisonOperators
   在IOrmAccesser接口中,很多方法都接受 params Filter[] conditions 或IList<Filter>参数,比如:
        void Delete(IList<Filter> conditions);
        
void Delete(params Filter[] conditions);
   比如,要删除数据库Student表中所有Age大于20岁且为男性的学生记录
 stuOrmAccesser.Delete(new Filter(Student._Age, 20, ComparisonOperators.Greater), new Filter(Student._IsBoy, true, ComparisonOperators.Equal));
   
   针对接受 params Filter[] conditions 或IList<Filter>参数的方法,在OrmAccesser内部将会对每个Filter所表示的单个条件进行“与”操作,来作为搜索条件。那么如果需要对各个Filter进行“或”操作,或进行更复杂的逻辑组合(如“filter1 && (filter2 || filter3)”),就需要采用对应的接受IFilterTree作为参数的重载方法。

3.IFilterTree
   IFilterTree 用于表示多个Filter的逻辑组合。
   
   注意,IFilterTree中也包含一个GetBooleanExpression()方法,该方法将当前Filter通过逻辑组合转换为一个标准的Sql条件字句。
   当前的IFilterTree有两个默认实现:
(1)SimpleFilterTree
   该实现仅仅支持最简单的对多个条件都进行“与”或都进行“或”的逻辑操作,更复杂的逻辑组合需求,可以使用AgileFilterTree。
   如果将上述的例子,改用IFilterTree可以这样实现:
            IList<Filter> conditions = new List<Filter>();
            conditions.Add(
new Filter(Student._Age, 20, ComparisonOperators.Greater));
            conditions.Add(
new Filter(Student._IsBoy, true, ComparisonOperators.Equal));
            IFilterTree conditionTree 
= new SimpleFilterTree(LogicType.And, conditions);
         
   stuOrmAccesser.Delete(conditionTree);

(2)AgileFilterTree
   AgileFilterTree 可以表示非常复杂的多个Filter的逻辑组合。它使用一个logicExpression字符串描述逻辑组合表达式,如"filter1 && (filter2 || filter3)",然后解析这个表达式获取正确的Sql条件语句。
   比如,我们要找出所有年龄在20与25岁之间,或者名字为sky的学生:
            IDictionary<string, Filter> mapping = new Dictionary<string, Filter>();
            mapping.Add(
"A"new Filter(Student._Name, "sky", ComparisonOperators.Equal));
            mapping.Add(
"B"new Filter(Student._Age, 20, ComparisonOperators.Greater));
            mapping.Add(
"C"new Filter(Student._Age, 25, ComparisonOperators.Less));
            IFilterTree agileTree 
= new AgileFilterTree("A||(B&&C)", mapping);

            IList<Student> list = stuOrmAccesser.GetMuch(agileTree);


4.IOrmAccesser的泛型参数
   IOrmAccesser是一个泛型接口,泛型参数是EntityType--即实体的类型,我们知道,每个EntityType对应着数据库中的一个表,Entity class的名字最好与数据表的名字一致,这样IOrmAccesser就可以根据EntityType知道要访问数据库中的哪个表。如果Entity class的名字最好与数据表的名字不一致,也没关系,我们可以通过向IDataAccesser的OrmCoagent属性注入IOrmCoagent来提供EntityType与数据表名称的映射关系。IOrmCoagent接口定义如下:
    public interface IOrmCoagent
    {
        
/// <summary>
        
/// GetTableName 根据Entity类型获取对应的数据库表名
        
/// </summary>        
        string GetTableName(Type entityType);
    }
   IOrmAccesser可以通过IOrmCoagent的GetTableName()方法来获取EntityType所对应的数据库表的名称。

5.基本"CRUD"方法

   IOrmAccesser提供了基本的“CRUD”方法,如Insert,Update,Delete,GetOne,GetMuch,GetDataSet等等。这些方法都提供了多个重载,以接收单个Filter条件或多个Filter以及IFilterTree。
   大多数方法的含义都特别清晰明了,有几个方法的含义需要特别指出一下:
        /// <summary>
        
/// GetMuchWithoutBlob 根据参数conditions来提取符合条件的所有Entity,但是Entity的blob字段没有被填充。
        
/// </summary>        
        IList<EntityType> GetMuchWithoutBlob(params Filter[] conditions);

        
/// <summary>
        
/// LoadBlob 填充entity的Blob字段
        
/// </summary>        
        void LoadBlob(EntityType entity);
        /// <summary>
        
/// Update 更新符合conditions的记录中由columnItems指定的各个Column为对应目标值。
        
/// </summary>        
        void Update(IList<ColumnItem> columnItems, IList<Filter> conditions);

        /// <summary>
        
/// GetDataSet 选取表中符合条件的row,并且只返回columns指定的列。
        
/// </summary>      
        DataSet GetDataSet(IList<Filter> conditions, params string[] columns);

6.基于主外键关系进行Get获取
    IOrmAccesser会自动依据数据表的主外键关系来进行关系加载,比如,Student表中有MentorID字段(外键),对应Mentor表中的主键。那么,IOrmAccesser的GetParent方法,就可以根据指定的Student对象返回Mentor对象。
Mentor mentor = stuOrmAccesser.GetParent<Mentor>(student);
基于主外键关系进行Get的方法包括:
        /// <summary>
        
/// GetParent 依据entity中外键的值,获取主表中的实体。外键建立了"语义"上的"Master-Detail"关系
        
/// </summary>       
        ParentType GetParent<ParentType>(EntityType entity);

        
/// <summary>
        
/// GetForeigner 依据entity中名为fkeyName外键的值,获取主表中的对应实体。外键没有"语义"上的"Master-Detail"关系
        
/// </summary>       
        ForeignerType GetForeigner<ForeignerType>(EntityType entity ,string fkeyName);

        
/// <summary>
        
/// GetChildList 依据entity中主键的值,获取从表中的所有相关实体
        
/// </summary>
        IList<ChildType> GetChildList<ChildType>(EntityType entity);

        
/// <summary>
        
/// GetChildDataSet 依据entity中主键的值,获取从表中的所有相关记录
        
/// </summary>
        DataSet GetChildDataSet<ChildType>(EntityType entity);
        
#endregion

   本文简单介绍了IOrmAccesser的一些基本功能和使用,在后面的文章中将介绍一些IOrmAccesser高级用法


返回到:轻量的数据访问框架 --序  

 



 

posted on 2007-03-20 10:58 zhuweisky 阅读(3041) 评论(11)  编辑 收藏 网摘 所属分类: DataRabbit

评论

#1楼 2007-03-20 11:21 JesseZhao      

呵呵,不知道什么时候能有源代码出来啊   回复  引用  查看    

#2楼 2007-03-20 18:00 啊啊[未注册用户]

从文章中学到很多东西。
  回复  引用    

#3楼 2007-03-21 10:36 aa[未注册用户]

问一个不太相干的问题:
你用来显示各个类之间的关系使用的是什么工具?
  回复  引用    

#4楼[楼主] 2007-03-21 10:40 zhuweisky      

@aa:
VS2005自带的建模工具
  回复  引用  查看    

#5楼 2007-07-04 16:24 wang.seraph[未注册用户]

AgileFilterTree
有bug
比如
IDictionary<string, Filter> mapping = new Dictionary<string, Filter>();
mapping.Add("A", new Filter(Student._Name, "BBB", ComparisonOperators.Equal));
mapping.Add("B", new Filter(Student._Age, 20, ComparisonOperators.Greater));
这样产生的条件会很混乱
  回复  引用    

#6楼 2007-07-06 08:40 zhuweisky[未注册用户]

to wang.seraph:
IDictionary<string, Filter> mapping = new Dictionary<string, Filter>();
mapping.Add("*A", new Filter(Student._Name, "BBB", ComparisonOperators.Equal));
mapping.Add("*B", new Filter(Student._Age, 20, ComparisonOperators.Greater));

这样就可以了
  回复  引用    

#7楼 2007-07-08 15:34 wang.seraph[未注册用户]

我觉得这个是不是治标不治本?
new Filter(Student._Name, "BBB", ComparisonOperators.Equal)
他的"BBB"可能是由用户输入的,这样的话包含"*B"的概率是不是很大呢?
  回复  引用    

#8楼 2007-10-16 15:23 finkle[未注册用户]

请问有没有关系是 In 的比较符(ComparisonOperators里似乎没有)。如何完成类似 DataField In (...)的查询呢?   回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

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

0 680839





相关文章:

相关链接: