• wojilu系统的ORM代码解析[源代码结构分析,ObjectBase基类分析]


           wojilu系统有着完整的ORM系统,对于ORM系统,园子里面应该有很多很多高手了,我以前对于ORM系统也没有什么研究,借着学习wojilu系统,顺便学习了一下wojilu的ORM代码,已经一个ORM的实现过程。

        首先来看一下wojilu系统的ORM部分的代码的位置:wojilu\ORM

    ListORMSource

                在学习wojilu的代码之前,我们先来想象一下他的代码大概是什么样子的。研究别人的代码之前,一定要自己先做一个预测,就像考试一样,自己先把题目做一遍,然后看答案,这样才能学习到东西,如果光看答案,自己失去了独立思考的机会,可能会被一个错误的答案误导。

           ORM系统,就是将Object通过Mapping的方法放入RationShip的数据库中。将对象通过映射放入关系数据库中。他需要的东西有

           1.一套对象基本类型到数据库类型的映射规则,例如将长整形int16,映射为数据库的长整形,将DateTime映射到DateTimeStamp,将String映射到varChar等等。

          2.一套反射机制,通过反射可以遍历对象的内部所有公开的属性。

          3.一套数据库自动访问系统,有一些基础的数据库访问方法,让开发者感觉不到在访问数据库。为了实现这个功能,必然有一个自动的Sql文生成系统。

    大概就是这些东西了,这里是我的答案,接下来,我们看看wojilu的答案。当然,wojilu的答案并非标准答案,ORM系统,没有标准答案,也不需要标准答案,能够符合你的项目的答案就是好的答案。

            在很多ORM系统里面,都有一个ObjectBase的类,这个类是万物之源,ORM都是围绕着这个万物之源展开的,只有将一个对象继承自ObjectBase,才能够享受到ORM的便利。换句话说,继承自ObjectBase的东西,都被纳入到了ORM的托管范围之内了。wojilu也有一个万物之源的类,这个类的源代码在wojilu\_wojilu\ObjectBase.cs

    下面截取一部分代码:

     1 namespace wojilu {
     2 
     3     /// <summary>
     4     /// 所有ORM中的领域模型都需要继承的基类
     5     /// </summary>
     6     /// <typeparam name="T"></typeparam>
     7     [Serializable]
     8     public class ObjectBase<T> : IEntity, IComparable where T : ObjectBase<T> {
     9 
    10         private int _id;
    11 
    12         /// <summary>
    13         /// 对象的 id
    14         /// </summary>
    15         public int Id {
    16             get { return _id; }
    17             set { this.setId( value ); _id = value; }
    18         }
    19 
    20         protected virtual void setId( int id ) {
    21         }
    22 
    23         /// <summary>
    24         /// 查询所有数据
    25         /// </summary>
    26         /// <returns></returns>
    27         public static List<T> findAll() { return db.findAll<T>(); }
    28 
    29         /// <summary>
    30         /// 根据 id 查询对象
    31         /// </summary>
    32         /// <param name="id"></param>
    33         /// <returns></returns>
    34         public static T findById( int id ) { return db.findById<T>( id ); }
    35 
    36         /// <summary>
    37         /// 统计所有的数据量
    38         /// </summary>
    39         /// <returns></returns>
    40         public static int count() { return db.count<T>(); }

     这里定义了ORM使用的多个方法的接口,也是整个ORM的基础,我们可以从分析这个类来分析整个wojiluORM系统。

     这个类需要实现IEntity, IComparable两个接口。

    第一个接口IEntity,实体接口:看看它的代码

    每一个Orm对象,都具有一个ID属性,这个属性,如果关注wojilu系统的话,这个ID是缓存系统的关键字,同样ID的内容,都是从缓存中获取的。ID作为是否缓存命中的一个依据。

    另外还有一个Get和SET的方法,获取或者设定某个属性的值。(并非通过反射,速度较快)
    这句话的意思,暂时还不是很清楚,可能通过进一步的学习能够理解吧。

     1   /// <summary>
     2     /// 可以被 ORM 持久化的对象,都自动实现了本接口
     3     /// </summary>
     4     public interface IEntity {
     5 
     6         /// <summary>
     7         /// 每一个持久化对象,都具有一个 Id 属性
     8         /// </summary>
     9         int Id { getset; }
    10 
    11         /// <summary>
    12         /// 获取属性的值(并非通过反射,速度较快)
    13         /// </summary>
    14         /// <param name="propertyName">属性名称</param>
    15         /// <returns></returns>
    16         Object get( String propertyName );
    17 
    18         /// <summary>
    19         /// 设置属性的值(并非通过反射,速度较快)
    20         /// </summary>
    21         /// <param name="propertyName">属性名称</param>
    22         /// <param name="propertyValue">属性的值</param>
    23         void set( String propertyName, Object propertyValue );
    24 
    25         /// <summary>
    26         /// 包括对象的元数据,以及在对象查询的时候需要的额外信息,不常用
    27         /// </summary>
    28         //ObjectInfo state { get; set; }
    29     }
    30 
    31 
    32 
    33 }

    具体的实现方法,源代码里面交代的很仔细了,截取部分代码:

     1         /// <summary>
     2         /// 根据属性名称获取属性的值
     3         /// </summary>
     4         /// <param name="propertyName">属性名称</param>
     5         /// <returns></returns>
     6         public Object get( String propertyName ) {
     7             EntityInfo ei = getEntityInfo();
     8             if (propertyName.IndexOf( "." ) < 0) {
     9                 EntityPropertyInfo ep = ei.GetProperty( propertyName );
    10                 if (ep == nullthrow new Exception( String.Format( "property '{1}' of {0} is empty", ei.FullName, propertyName ) );
    11                 return ep.GetValue( this );
    12             }
    13             String[] arrItems = propertyName.Split( new char[] { '.' } );
    14             Object result = null;
    15             ObjectBase<T> obj = this;
    16             for (int i = 0; i < arrItems.Length; i++) {
    17                 if (i < (arrItems.Length - 1)) {
    18                     obj = (ObjectBase<T>)obj.get( arrItems[i] );
    19                 }
    20                 else {
    21                     result = obj.get( arrItems[i] );
    22                 }
    23             }
    24             return result;
    25         }
    26 
    27         /// <summary>
    28         /// 设置属性的值
    29         /// </summary>
    30         /// <param name="propertyName">属性名称</param>
    31         /// <param name="propertyValue">属性的值</param>
    32         public void set( String propertyName, Object propertyValue ) {
    33             getEntityInfo().GetProperty( propertyName ).SetValue( this, propertyValue );
    34         }

      

    IComparable接口应该是系统自带的接口,这个接口一般是用来自动排序的。NET框架中已经有自带的排序的方法了,但是两个对象,如何比较大小,以什么规则来比较大小,是通过这个IComparable对象的代码来实现的。

    (MSDN:定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序。)

     

      名称 说明
    公共方法 CompareTo 将当前实例与同一类型的另一个对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。

    一般的排序操作,都是通过sql的Orderby来实现的,这里Compare的具体作用,暂时不明确。

    不过,我们先看看这个CompareTo方法的具体实现吧:

    1         /// <summary>
    2         /// 排序方法(根据Id大小排序)
    3         /// </summary>
    4         /// <param name="obj"></param>
    5         /// <returns></returns>
    6         public virtual int CompareTo( Object obj ) {
    7             return ((ObjectBase<T>)obj).Id.CompareTo( Id );
    8         }

    这里只是单纯通过比较ID来获得大小关系。在排序等操作中,ID作为默认的OrderBy关键字。

    这里只是wojiluORM的开篇。更多的内容请参看本系列的其他文章。

     wojilu系统的ORM介绍

     ORM中启用数据库事务

  • 相关阅读:
    Flask 开启跨域
    pandas to dict
    mongodb 聚合查询
    flask 获取请求参数
    CSS dppx详解
    用CSS做出漂亮的字体动画
    VMware虚拟主机安装完成后连接不上网络
    wokerman中自定义协议的使用和测试
    使用workerman写一个小的聊天室
    telnet不能使用怎么办?
  • 原文地址:https://www.cnblogs.com/TextEditor/p/2090560.html
Copyright © 2020-2023  润新知