• ORM映射框架总结SQL 语句生成组件


     1.       SQL 语句生成组建

    之前说过ORM框架中有一个非常重要的组件,那就是SQL语句生成组件。SQL语句生成组件,顾名思义就是用于生成sql语句的一个组件。之前的Attribute 是用于修饰实体信息,而上一章讲的实体分析器分析了实体信息,在很大一部分程度上,以上做工作就是为这个SQL语句生成组件服务的。

    该组件的核心接口是IDbFactory,它实现了接口IDisposable

    目前该ORM支持SQL Server 数据库的sql语句生成,在后期过程中会逐步实现对Oracle,Mysql,Access 等数据库的支持

    下面是该接口定义的方法图表:

    2.       核心接口

    核心接口定义源码

    核心接口定义源码
      1 /**
      2  * 2010-2-2
      3  * 
      4  * 情 缘
      5  * 
      6  * IDbFactory 接口实现了IDisposable 接口,实现该
      7  * 接口的类可以通过IDisposable 接口来释放对象占用
      8  * 的内存。该接口的主要作用适用于根据实体对象来创
      9  * 建SQL Server 数据库脚本。ORM 的主要作用是为了
     10  * 实现对象化操作数据库,而此操作就是为了实现对象
     11  * 化操作和数据库语句操作的过渡
     12  * 
     13  * */
     14 using System;
     15 using System.Collections.Generic;
     16 using System.Linq;
     17 using System.Text;
     18 using CommonData.Entity;
     19 using System.Data;
     20 using CommonData.Model.Core;
     21 
     22 namespace CommonData.Data.Core
     23 {
     24     public interface IDbFactory : IDisposable
     25     {
     26         /// <summary>
     27         /// 根据实体对象公共接口创建插入的sql语句
     28         /// </summary>
     29         /// <param name="entity">实体公共接口</param>
     30         /// <param name="param">创建sql语句对应占位符参数</param>
     31         /// <returns></returns>
     32         string CreateInsertSql(IEntity entity, out IDataParameter[] param);
     33 
     34         /// <summary>
     35         /// 根据实体类型创建插入sql语句
     36         /// </summary>
     37         /// <param name="type">实体类型</param>
     38         /// <param name="value">实体对象</param>
     39         /// <param name="param">创建sql语句对应占位符参数</param>
     40         /// <returns></returns>
     41         string CreateInsertSql(Type type, object value, out IDataParameter[] param);
     42 
     43         /// <summary>
     44         /// 根据泛型类型创建插入sql语句
     45         /// </summary>
     46         /// <typeparam name="T">泛型类型</typeparam>
     47         /// <param name="t">泛型实体类</param>
     48         /// <param name="param">创建sql语句对应占位符参数</param>
     49         /// <returns></returns>
     50         string CreateInsertSql<T>(T t, out IDataParameter[] param) where T : IEntity;
     51 
     52         /// <summary>
     53         /// 根据实体对象公共接口创建修改的的sql语句
     54         /// 该sql语句是根据主键列修改的
     55         /// </summary>
     56         /// <param name="entity">实体公共接口</param>
     57         /// <param name="param">创建sql语句对应占位符参数</param>
     58         /// <returns></returns>
     59         string CreateUpdateSql(IEntity entity, out IDataParameter[] param);
     60 
     61         /// <summary>
     62         /// 根据实体对象类型创建修改的的sql语句
     63         /// </summary>
     64         /// <param name="type">实体类型</param>
     65         /// <param name="value">实体对象</param>
     66         /// <param name="param">创建sql语句对应占位符参数</param>
     67         /// <returns></returns>
     68         string CreateUpdateSql(Type type, object value, out IDataParameter[] param);
     69 
     70         /// <summary>
     71         /// 根据实体对象公共接口创建修改的的sql语句
     72         /// 该sql语句是根据一个特定的属性作为修改条件的
     73         /// </summary>
     74         /// <param name="entity">实体公共接口</param>
     75         /// <param name="param">创建sql语句对应占位符参数</param>
     76         /// <param name="propertyName">属性名称</param>
     77         /// <returns></returns>
     78         string CreateUpdateSql(IEntity entity, out IDataParameter[] param, string propertyName);
     79 
     80         /// <summary>
     81         /// 根据实体对象类型创建修改的的sql语句
     82         /// 该sql语句是根据一个特定的属性作为修改条件的
     83         /// </summary>
     84         /// <param name="type">实体类型</param>
     85         /// <param name="value">实体对象</param>
     86         /// <param name="param">创建sql语句对应占位符参数</param>
     87         /// <param name="propertyName">属性名称</param>
     88         /// <returns></returns>
     89         string CreateUpdateSql(Type type, object value, out IDataParameter[] param, string propertyName);
     90 
     91         /// <summary>
     92         /// 根据实体对象公共接口创建修改的的sql语句
     93         /// 该sql语句是根据多个特定的属性作为修改条件的
     94         /// </summary>
     95         /// <param name="entity">实体公共接口</param>
     96         /// <param name="param">创建sql语句对应占位符参数</param>
     97         /// <param name="propertyNames">属性名称</param>
     98         /// <returns></returns>
     99         string CreateUpdateSql(IEntity entity, out IDataParameter[] param, string[] propertyNames);
    100 
    101         /// <summary>
    102         /// 根据实体对象类型创建修改的的sql语句
    103         /// 该sql语句是根据多个特定的属性作为修改条件的
    104         /// </summary>
    105         /// <param name="type">实体类型</param>
    106         /// <param name="value">实体对象</param>
    107         /// <param name="param">创建sql语句对应占位符参数</param>
    108         /// <param name="propertyNames">属性名称</param>
    109         /// <returns></returns>
    110         string CreateUpdateSql(Type type, object value, out IDataParameter[] param, string[] propertyNames);
    111 
    112         /// <summary>
    113         /// 根据实体对象公共接口创建修改的的sql语句
    114         /// 该sql语句是根据查询组建创建的
    115         /// </summary>
    116         /// <param name="entity">实体公共接口</param>
    117         /// <param name="param">创建sql语句对应占位符参数</param>
    118         /// <param name="component">查询条件组件</param>
    119         /// <returns></returns>
    120         string CreateUpdateSql(IEntity entity, out IDataParameter[] param, ConditionComponent component);
    121 
    122         /// <summary>
    123         /// 根据实体对象公共接口创建删除sql语句
    124         /// 该sql语句是根据实体主键删除
    125         /// </summary>
    126         /// <param name="entity">实体公共接口</param>
    127         /// <param name="param">创建sql语句对应占位符参数</param>
    128         /// <returns></returns>
    129         string CreateDeleteSql(IEntity entity, out IDataParameter[] param);
    130 
    131         /// <summary>
    132         /// 根据实体对象类型创建删除sql语句
    133         /// 该sql语句是根据实体主键删除
    134         /// </summary>
    135         /// <param name="type">实体类型</param>
    136         /// <param name="value">实体对象</param>
    137         /// <param name="param">创建sql语句对应占位符参数</param>
    138         /// <returns></returns>
    139         string CreateDeleteSql(Type type,object value,out IDataParameter[] param);
    140 
    141         /// <summary>
    142         /// 根据实体对象公共接口的某个属性创建删除sql语句
    143         /// 该sql语句是根据实体属性删除
    144         /// </summary>
    145         /// <param name="entity">实体公共接口</param>
    146         /// <param name="param">创建sql语句对应占位符参数</param>
    147         /// <param name="propertyName">实体属性名称</param>
    148         /// <returns></returns>
    149         string CreateDeleteSql(IEntity entity, out IDataParameter[] param, string propertyName);
    150 
    151         /// <summary>
    152         /// 根据实体对象类型的某个属性创建删除sql语句
    153         /// 该sql语句是根据实体属性删除
    154         /// </summary>
    155         /// <param name="type">实体类型</param>
    156         /// <param name="value">实体对象</param>
    157         /// <param name="param">创建sql语句对应占位符参数</param>
    158         /// <param name="propertyName">实体属性名称</param>
    159         /// <returns></returns>
    160         string CreateDeleteSql(Type type, object value, out IDataParameter[] param, string propertyName);
    161 
    162         /// <summary>
    163         /// 根据实体对象公共接口的多个属性创建删除sql语句
    164         /// 该sql语句是根据实体多个属性删除
    165         /// </summary>
    166         /// <param name="entity">实体公共接口</param>
    167         /// <param name="param">创建sql语句对应占位符参数</param>
    168         /// <param name="propertyName">实体属性名称数组</param>
    169         /// <returns></returns>
    170         string CreateDeleteSql(IEntity entity, out IDataParameter[] param, string[] propertyNames);
    171 
    172         /// <summary>
    173         /// 根据实体对象类型的多个属性创建删除sql语句
    174         /// 该sql语句是根据实体多个属性删除
    175         /// </summary>
    176         /// <param name="type">实体了姓</param>
    177         /// <param name="value">实体对象</param>
    178         /// <param name="param">创建sql语句对应占位符参数</param>
    179         /// <param name="propertyNames">实体属性名称数组</param>
    180         /// <returns></returns>
    181         string CreateDeleteSql(Type type, object value, out IDataParameter[] param, string[] propertyNames);
    182 
    183         /// <summary>
    184         /// 根据实体对象公共接口的多个属性创建删除sql语句
    185         /// 该sql语句使根据查询组建来创建的
    186         /// </summary>
    187         /// <param name="entity">实体公共接口</param>
    188         /// <param name="param">创建sql语句对应占位符参数</param>
    189         /// <param name="component">实体属性名称数组</param>
    190         /// <returns></returns>
    191         string CreateDeleteSql(IEntity entity, out IDataParameter[] param, ConditionComponent component);
    192 
    193         /// <summary>
    194         /// 根据实体的公共接口创建查询单行数据的sql语句
    195         /// 该sql语句是根据数据库表的主键来查询的
    196         /// </summary>
    197         /// <param name="entity">实体公共接口</param>
    198         /// <param name="param">创建sql语句对应占位符参数</param>
    199         /// <returns></returns>
    200         string CreateSingleSql(IEntity entity, out IDataParameter[] param);
    201 
    202         /// <summary>
    203         /// 根据实体的公共接口创建查询单行数据的sql语句
    204         /// 该sql语句是根据实体的相应属性来查询
    205         /// </summary>
    206         /// <param name="entity">实体公共接口</param>
    207         /// <param name="param">创建sql语句对应占位符参数</param>
    208         /// <returns></returns>
    209         string CreateSingleSql(IEntity entity, out IDataParameter[] param, string[] propertyNames);
    210 
    211         /// <summary>
    212         /// 根据实体类型创建查询单行数据的sql语句
    213         /// 该sql语句是根据实体的相应属性来查询
    214         /// </summary>
    215         /// <param name="type">实体类型</param>
    216         /// <param name="value">实体对象</param>
    217         /// <param name="param">创建sql语句对应占位符参数</param>
    218         /// <param name="propertyNames">属性名称数组</param>
    219         /// <returns></returns>
    220         string CreateSingleSql(Type type, object value, out IDataParameter[] param, string[] propertyNames);
    221 
    222         /// <summary>
    223         /// 根据实体的类型创建查询sql语句
    224         /// </summary>
    225         /// <param name="entityType">实体类型</param>
    226         /// <returns></returns>
    227         string CreateSingleSql(Type entityType);
    228 
    229         /// <summary>
    230         /// 根据实体的类型创建查询sql语句,
    231         /// 该方法指定主键值
    232         /// </summary>
    233         /// <param name="type">实体类型</param>
    234         /// <param name="pkPropertyValue">主键值</param>
    235         /// <param name="param">创建sql语句对应占位符参数</param>
    236         /// <returns></returns>
    237         string CreateSingleSql(Type type, object pkPropertyValue,out IDataParameter[] param);
    238 
    239         /// <summary>
    240         /// 根据实体的类型创建查询该实体对象对应数据库表的所有数据的sql语句
    241         /// 该sql语句用于查询所有数据,并转换为相应List<T> 集合
    242         /// </summary>
    243         /// <param name="type">实体的类型</param>
    244         /// <returns></returns>
    245         string CreateQuerySql(Type type);
    246 
    247         /// <summary>
    248         /// 根据实体的某个属性创建根据该属性字段查询数据的sql语句
    249         /// 该sql语句是使用参数中属性对应字段作为条件查询的
    250         /// </summary>
    251         /// <param name="type">实体类型</param>
    252         /// <param name="propertyName">属性名称</param>
    253         /// <param name="value">属性值</param>
    254         /// <param name="param">sql语句占位符参数</param>
    255         /// <returns></returns>
    256         string CreateQueryByPropertySql(Type type, string propertyName, object value, out IDataParameter[] param);
    257 
    258         /// <summary>
    259         /// 根据实体的某些属性创建根据该些属性字段查询数据的sql语句
    260         /// 该sql语句是使用参数中属性对应字段作为条件查询的,并且该
    261         /// 属性集合都是根据and条件组装的
    262         /// </summary>
    263         /// <param name="type">实体类型</param>
    264         /// <param name="dic">属性-值集合</param>
    265         /// <param name="param">sql语句占位符参数</param>
    266         /// <returns></returns>
    267         string CreateQueryByPropertySql(Type type, IDictionary<stringobject> dic, out IDataParameter[] param);
    268 
    269         /// <summary>
    270         /// 根据实体的某些属性创建根据该些属性字段查询数据的sql语句
    271         /// 该sql语句是使用参数中属性对应字段作为条件查询的,并且查
    272         /// 询是根据查询组建来创建
    273         /// </summary>
    274         /// <param name="type">实体类型</param>
    275         /// <param name="dic">属性-值集合</param>
    276         /// <param name="param">sql语句占位符参数</param>
    277         /// <param name="component">查询组建</param>
    278         /// <returns></returns>
    279         string CreateQueryByPropertySql(Type type, IDictionary<stringobject> dic, out IDataParameter[] param, ConditionComponent component);
    280 
    281         /// <summary>
    282         /// 根据实体类型来创建该实体对应数据库表的聚合函数查询sql语句
    283         /// 该方法创建的sql语句主要是用于查询数据行数
    284         /// </summary>
    285         /// <param name="type">实体类型</param>
    286         /// <param name="converage">聚合函数枚举类型</param>
    287         /// <returns></returns>
    288         string CreateConverageSql(Type type, Converage converage);
    289 
    290         /// <summary>
    291         /// 根据实体类型来创建该实体对应数据库表的聚合函数查询sql语句
    292         /// 该方法创建的sql语句主要是用于统计查询(最大值,最小值,求和,平均值,数据行数)
    293         /// </summary>
    294         /// <param name="type">实体类型</param>
    295         /// <param name="converage">聚合函数枚举类型</param>
    296         /// <param name="propertyName">聚合函数作用的属性名称</param>
    297         /// <returns></returns>
    298         string CreateConverageSql(Type type, Converage converage, string propertyName);
    299 
    300         /// <summary>
    301         /// 根据实体类型来创建该实体对应数据库表的聚合函数查询sql语句
    302         /// 该方法创建的sql语句主要是用于统计查询(最大值,最小值,求和,平均值,数据行数),
    303         /// 同时该sql是有条件查询的
    304         /// </summary>
    305         /// <param name="type">实体类型</param>
    306         /// <param name="converage">聚合函数枚举类型</param>
    307         /// <param name="propertyName">聚合函数作用的属性名称</param>
    308         /// <param name="dic">查询条件属性键值</param>
    309         /// <param name="component">查询条件组建对象</param>
    310         /// <returns></returns>
    311         string CreateConverageSql(Type type, Converage converage, string propertyName, IDictionary<stringobject> dic, out IDataParameter[] param, ConditionComponent component);
    312 
    313         /// <summary>
    314         /// 根据占位符名称创建参数
    315         /// </summary>
    316         /// <param name="name">占位符名称</param>
    317         /// <returns></returns>
    318         IDataParameter CreateParameter(string name);
    319 
    320         /// <summary>
    321         /// 根据占位符和值创建参数
    322         /// </summary>
    323         /// <param name="name">占位符名称</param>
    324         /// <param name="value">占位符的值</param>
    325         /// <returns></returns>
    326         IDataParameter CreateParameter(string name, object value);
    327 
    328         /// <summary>
    329         /// 根据占位符名称,类型和值创建参数
    330         /// </summary>
    331         /// <param name="name">占位符名称</param>
    332         /// <param name="type">参数的类型</param>
    333         /// <param name="value">参数的值</param>
    334         /// <returns></returns>
    335         IDataParameter CreateParameter(string name, DataType type, object value);
    336 
    337         /// <summary>
    338         /// 根据占位符的名称,类型和大小创建参数
    339         /// </summary>
    340         /// <param name="name">占位符名称</param>
    341         /// <param name="type">参数类型</param>
    342         /// <param name="size">参数值大小</param>
    343         /// <returns></returns>
    344         IDataParameter CreateParameter(string name, DataType type, int size);
    345 
    346         /// <summary>
    347         /// 根据占位符的名称,类型,大小和值创建参数
    348         /// </summary>
    349         /// <param name="name">占位符名称</param>
    350         /// <param name="type">参数类型</param>
    351         /// <param name="size">参数大小</param>
    352         /// <param name="value">参数值</param>
    353         /// <returns></returns>
    354         IDataParameter CreateParameter(string name, DataType type, int size, object value);
    355 
    356         /// <summary>
    357         /// 根据占位符名称和类型创建参数
    358         /// </summary>
    359         /// <param name="name">占位符名称</param>
    360         /// <param name="type">占位符类型</param>
    361         /// <returns></returns>
    362         IDataParameter CreateParameter(string name, DataType type);
    363     }
    364 }
    365 

      

       该接口定了生成增删改查等sql语句的方法

    CreateInsertSql() 方法主要用于生成插入语句,该方法被重载了3次,根据各种不同的情况来生成数据库插入sql语句。

    CreateUpdateSql() 方法主要用于生成修改语句,该方法被重载了7次,根据各种不同的情况来生成数据的修改sql语句。

    CreateDeleteSql() 方法主要用于生成删除语句,该方法同样被重载了7,根据各种不同的情况来生成数据库的删除sql语句。

    CreateSingleSql() 方法主要用于生成查询单个实体的sql语句,该方法被重载了5,根据各种不同的情况来生成数据库的单数据行sql语句。

    CreateQuerySql() 方法主要用于生成查询集合的sql语句,该方法只被重载了一次,从上面的源码中可以看出,该方法只有一个Type类型参数,此方法不做正在意义上查询使用,此方法在配合级联查询的时候能够起到重要的作用。

    CreateQueryByPropertySql() 方法主要生成条件查询的sql语句,该方法被充值了3,根据不同的情况来生成数据的集合查询的sql语句。注意该方法中引入了一个新的对象ConditionComponent在后面的说明中对次类进行讲解。

    CreateConverageSql() 方法主要用于生成查询聚合函数的sql语句,该方法同样被重载了3次,根据不同的情况来生成查询聚合函数的sql语句。该方法同样也引入了一个新的对象Converage在后面的说明中对次类进行讲解。

    CreateParameter() 方法主要用于生成sql语句占位符参数的,该方法被重载了6次。

    以上是该核心接口定义的几组方法,用于生成sql语句。在程序设计的过程中,都采用的面向接口来编程,目前来说只支持sql server 数据的sql语句生成,但是考虑到后期的补充,觉得在使用接口编程就尤为重要。后期的工作就是根据不同的数据库去实现该接口中的所有方法。

    3.       插入sql语句的生成

    上面说到了插入sql语句被重载了3次,在很多情况下我们根据情况的不同生成sql语句所需的方式也不同,于是归纳成了三个重载方法,该三个重载放一般情况下是可以覆盖所有的生成插入语句的情况。

    string CreateInsertSql(IEntity entity, out IDataParameter[] param);

    在上面的桥梁映射过程中,我们提到了一个接口IEntity,它是所有实体的父级接口,该接口并未定义任何方法,或许当时有人认为这是多此一举,不过现在大家应该明白了,这样定义是有缘由的。因为这个插入语句的生成要覆盖所有的实体类,于是我们必须抽象出来,抽象它们共同拥有的特性。在这里,这个IEntity 接口的重要性显得尤为突出。Param参数这是用于存储sql语句的占位符的,看到这个参数的修饰符out,说明参数传入本身是空的,也就是说在后期的实现过程中我们要动态的去给param赋值,参数名,参数值,以及数组的长度都是由entity 来决定。

    string CreateInsertSql(Type type, object value, out IDataParameter[] param);

    说到重载,这是面向对象编程的四要素之一,多态表现形式之一,另外一种是重写。重载其实要实现的功能是一样,只是表现形式不同而已,这里使用了Type,这里就是要插入的实体的类型,后面的object value 就是实体,紧接着的参数就不用多说了,上面的方法已经提到过。

    string CreateInsertSql<T>(T t, out IDataParameter[] param) where T : IEntity

    说到这个重载方法,大家一般都会很兴奋,为什么.我第一眼看到了<T> .net中的泛型。.net中的泛型我可以说真的是无懈可击,那各种形态的使用方式是如此的婀娜多姿,总是让程序员沉迷于其中的美妙,最起码我是这样的。后面的where T : IEntity 就是泛型约束了,泛型约束可以让我们的程序减少很多不必要的麻烦。因为泛型本身就是一种不确定的类型,我们规定了他使用的范围,这样能够减少它出错的可能性。

    下面看看这个插入sql的生成核心代码:

    插入sql的生成核心代码
     1 /// <summary>
     2         /// 根据实体类型创建插入sql语句
     3         /// </summary>
     4         /// <param name="type">实体类型</param>
     5         /// <param name="value">实体对象</param>
     6         /// <param name="param">创建sql语句对应占位符参数</param>
     7         /// <returns></returns>
     8         public string CreateInsertSql(Type type, object value, out IDataParameter[] param)
     9         {
    10             if (value == null)
    11             {
    12                 throw new NullReferenceException("the save entity is null");
    13             }
    14             StringBuilder sbColumn = new StringBuilder("");
    15             StringBuilder sbValues = new StringBuilder("");
    16             IDictionary<string, ColumnAttribute> dicColumn = EntityTypeCache.GetTableInfo(type).DicColumns;
    17             if (dicColumn.Keys.Count > 0)
    18             {
    19                 sbColumn.AppendFormat("insert into {0} (", EntityTypeCache.GetTableInfo(type).Table.Name);
    20                 sbValues.AppendFormat(" values (");
    21                 IList<IDataParameter> listParams = new List<IDataParameter>();
    22                 foreach (string key in dicColumn.Keys)
    23                 {
    24                     if (!dicColumn[key].AutoIncrement)
    25                     {
    26                         sbColumn.AppendFormat("{0},", dicColumn[key].Name);
    27                         sbValues.AppendFormat("{0},""@" + dicColumn[key].Name);
    28                     }
    29                     if (EntityFactory.GetPropertyValue(value, key) == null)
    30                     {
    31                         listParams.Add(CreateParameter("@" + key, System.DBNull.Value));
    32                     }
    33                     else
    34                     {
    35                         listParams.Add(CreateParameter("@" + key, EntityFactory.GetPropertyValue(value, key)));
    36                     }
    37                 }
    38                 sbColumn.Replace(","")", sbColumn.Length - 11);
    39                 sbValues.Replace(","")", sbValues.Length - 11);
    40                 param = listParams.ToArray();
    41                 return sbColumn.ToString() + sbValues.ToString();
    42             }
    43             else
    44             {
    45                 param = null;
    46                 return null;
    47             }
    48         }

        当大家看到这里肯定也觉得,原理这个东西也不过如此。如果真是这样,那我也就替你高兴了,因为我要传达的意思你已经明白了,也就是说我写这边博文的传达的信息你收到了。一次完美的会话完成。

        StringBuilder sbColumn = new StringBuilder("");

    StringBuilder sbValues = new StringBuilder("");

    代码中定义了这两个类,不使用string的原因大家也知道。还有这里我们生成sql语句的规则就是sql语句插入的语法规则,这里不再多说。

    4.       修改sql语句

    生成修改sql语句的方法CreateUpdateSql()被重载了七次,其实生成sql语句的原理和上面生成插入sql语句的原理是一样的。关键在于如何去抽象一个多情况下处理方式。

    string CreateUpdateSql(IEntity entity, out IDataParameter[] param);

    这个方法主要是根据实体的主键作为条件来修改

    string CreateUpdateSql(IEntity entity, out IDataParameter[] param, string[] propertyNames);

    这个方法则是根据实体的过个属性来修改,各个条件以and方式来连接生成sql语句。在生成sql语句的过程中IEntity 必须包含这些数据,而且这些属性值必须存在,否则会抛出异常。与此类似的方法还有只有一个属性名来修改的,其实这个方法可以包括只有一个属性的修改方法,而这里重载一次就是为了使用方便。

    string CreateUpdateSql(IEntity entity, out IDataParameter[] param, ConditionComponent component);

    这里我们不介绍其他东西了,主要看看ConditionComponent这个类。上面提到过如果多条件修改sql语句,各个属性都是通过and来连接的,如果我们修改使用 or 或者其他的方式怎么办,ConditionComponent可以用来解决此问题。

    首先看看这个类的源码:

    查询组件存储器源码
     1 /**
     2  * 2010-3-1
     3  * 
     4  * 情 缘
     5  * 
     6  * 该类封装修改数据,条件查询数据的相关条件。
     7  * 
     8  * */
     9 using System;
    10 using System.Collections.Generic;
    11 using System.Linq;
    12 using System.Text;
    13 
    14 namespace CommonData.Model.Core
    15 {
    16     public class ConditionComponent
    17     {
    18         private IDictionary<string, SearchComponent> dicComponent = null;
    19 
    20         /// <summary>
    21         /// 用于存储属性查询类型
    22         /// </summary>
    23         public IDictionary<string, SearchComponent> DicComponent
    24         {
    25             get { return dicComponent; }
    26             set { dicComponent = value; }
    27         }
    28 
    29         private static ConditionComponent component;
    30 
    31         /// <summary>
    32         /// 私有构造方法,禁止外部类构造此类的实例
    33         /// 使用私有构造方式主要实现单例模式
    34         /// </summary>
    35         private ConditionComponent()
    36         { 
    37         
    38         }
    39 
    40         /// <summary>
    41         /// 构造ConditionComponent的实例,当实例不存在是则创建该对象
    42         /// 这个是单例模式的实现
    43         /// </summary>
    44         /// <returns></returns>
    45         public static ConditionComponent Instance()
    46         {
    47             if (component == null)
    48             {
    49                 component = new ConditionComponent();
    50                 component.DicComponent = new Dictionary<string, SearchComponent>();
    51             }
    52             return component;
    53         }
    54 
    55         /// <summary>
    56         /// 添加属性查询类型
    57         /// </summary>
    58         /// <param name="propertyName">属性名称</param>
    59         /// <param name="component">查询类型</param>
    60         /// <returns></returns>
    61         public ConditionComponent AddComponent(string propertyName,SearchComponent component)
    62         {
    63             if (component == null)
    64             {
    65                 ConditionComponent.component = Instance();
    66             }
    67             ConditionComponent.component.DicComponent.Add(propertyName, component);
    68             return ConditionComponent.component;
    69         }
    70 
    71     }
    72 }
    73 

       这个类其实就相当于一个存储器。

    private IDictionary<string, SearchComponent> dicComponent = null;

    dicComponent就是用于存储相应的数据的,而且是以键值对的方式存储,这样便于后面使用过程中的查找。而这里又出现了一个心得类SearchComponent,这个是查询条件组建。下面在讲解。这里定义了这个类的一个单例模式,也就是说只能允许一个对象的存在每次。我需要在每次天际参数的同时这个对象仍然存在,并且保存信息。

        public ConditionComponent AddComponent(string propertyName,SearchComponent component)

            {

                if (component == null)

                {

                    ConditionComponent.component = Instance();

                }

                ConditionComponent.component.DicComponent.Add(propertyName, component);

                return ConditionComponent.component;

         }

    这个方法每次给ConditionComponent添加一个参数,然后又返回这个对象。

    下面看看上面的提到的SearchComponent源码:

    查询组件枚举
     1 /**
     2  * 2010-3-1
     3  * 
     4  * 情 缘
     5  * 
     6  * 该类是一个枚举类型,定义了元素查询条件。
     7  * 该枚举值都一一对应数据库中的各种查询条
     8  * 件。
     9  * 
    10  * */
    11 using System;
    12 using System.Collections.Generic;
    13 using System.Linq;
    14 using System.Text;
    15 
    16 namespace CommonData.Model.Core
    17 {
    18     public enum SearchComponent
    19     {
    20         /// <summary>
    21         /// 对应数据库中的 "="
    22         /// </summary>
    23         Equals,
    24 
    25         /// <summary>
    26         /// 对应数据库中的 "!="
    27         /// </summary>
    28         UnEquals,
    29 
    30         /// <summary>
    31         /// 对应数据库中的 ">"
    32         /// </summary>
    33         Greater,
    34 
    35         /// <summary>
    36         /// 对应数据库中的 ">="
    37         /// </summary>
    38         GreaterOrEquals,
    39 
    40         /// <summary>
    41         /// 对应数据库中的 "<"
    42         /// </summary>
    43         Less,
    44         
    45         /// <summary>
    46         /// 对应数据库中的 "<="
    47         /// </summary>
    48         LessOrEquals,
    49 
    50         /// <summary>
    51         /// 对应数据库中的 "like"
    52         /// </summary>
    53         Like,
    54 
    55         /// <summary>
    56         /// 对应数据库中的 "in"
    57         /// </summary>
    58         In,
    59 
    60         /// <summary>
    61         /// 对应数据库中的 "between and"
    62         /// </summary>
    63         Between,
    64 
    65         /// <summary>
    66         /// 对应数据库中的 "order by asc"
    67         /// </summary>
    68         OrderAsc,
    69 
    70         /// <summary>
    71         /// 对应数据库中的 "order by desc"
    72         /// </summary>
    73         OrderDesc,
    74 
    75         /// <summary>
    76         /// 对应数据库中的 "group by"
    77         /// </summary>
    78         GroupBy,
    79 
    80         /// <summary>
    81         /// 对应数据库中的 "or"
    82         /// </summary>
    83         Or
    84     }
    85 }
    86 

    这里的代码大家一看也就明白了,为什么叫查询组件了,它其实就是封装了一些查询可能出现的情况。代码非常简单,这里不再过多讲解。

    下面是生成修改语句的方法实现,这个方法的代码包含了查询组件的运用:

    修改sql语句的实现
     1 /// <summary>
     2         /// 根据实体对象公共接口创建修改的的sql语句
     3         /// 该sql语句是根据查询组建创建的
     4         /// </summary>
     5         /// <param name="entity">实体公共接口</param>
     6         /// <param name="param">创建sql语句对应占位符参数</param>
     7         /// <param name="component">查询条件组件</param>
     8         /// <returns></returns>
     9         public string CreateUpdateSql(IEntity entity, out IDataParameter[] param, ConditionComponent component)
    10         {
    11 
    12             StringBuilder sbColumn = new StringBuilder("");
    13             StringBuilder sbValues = new StringBuilder("");
    14             IList<IDataParameter> listParams = new List<IDataParameter>();
    15             sbColumn.AppendFormat("update {0} set ", EntityTypeCache.GetTableInfo(entity).Table.Name);
    16             sbValues.Append(" where 1=1 ");
    17             foreach (string propertyName in EntityTypeCache.GetTableInfo(entity).DicProperties.Keys)
    18             {
    19                 //包含则作为条件
    20                 if (component.DicComponent.Keys.Contains(propertyName))
    21                 {
    22                     switch (component.DicComponent[propertyName])
    23                     {
    24                         case SearchComponent.Equals:
    25                             sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, "=", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name);
    26                             break;
    27                         case SearchComponent.UnEquals:
    28                             sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, "!=", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name);
    29                             break;
    30                         case SearchComponent.Between:
    31                             break;
    32                         case SearchComponent.Greater:
    33                             sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, ">", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name);
    34                             break;
    35                         case SearchComponent.GreaterOrEquals:
    36                             sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, ">=", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name);
    37                             break;
    38                         case SearchComponent.GroupBy:
    39                             break;
    40                         case SearchComponent.In:
    41                             break;
    42                         case SearchComponent.Less:
    43                             sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, "<", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name);
    44                             break;
    45                         case SearchComponent.LessOrEquals:
    46                             sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, "<=", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name);
    47                             break;
    48                         case SearchComponent.Like:
    49                             break;
    50                         case SearchComponent.Or:
    51                             break;
    52                         case SearchComponent.OrderAsc:
    53                             break;
    54                         case SearchComponent.OrderDesc:
    55                             break;
    56                     }
    57                     listParams.Add(CreateParameter("@" + EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, EntityFactory.GetPropertyValue(entity, propertyName) == null ? DBNull.Value : EntityFactory.GetPropertyValue(entity, propertyName)));
    58                 }
    59                 else  //判断主键和唯一列,主键和唯一列不能被修改
    60                 {
    61                     if (EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].IsPrimaryKey ||
    62                         EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].IsUnique ||
    63                         EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].AutoIncrement)
    64                     {
    65 
    66                     }
    67                     else
    68                     {
    69                         sbColumn.AppendFormat("{0}=@{1},", EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name);
    70                         listParams.Add(CreateParameter("@" + EntityTypeCache.GetTableInfo(entity).DicColumns[propertyName].Name, EntityFactory.GetPropertyValue(entity, propertyName) == null ? DBNull.Value : EntityFactory.GetPropertyValue(entity, propertyName)));
    71                     }
    72                 }
    73             }
    74             sbColumn.Remove(sbColumn.Length - 11);
    75             param = listParams.ToArray();
    76             return sbColumn.ToString() + sbValues.ToString();
    77         }

    5.       聚合函数的使用

    这里不做过多的降解了,都是前篇一律的,不过有个特殊的地方,那就是刚才提到过来的Converage

    先看看这个枚举的源码:

    聚合函数Converage枚举
     1 /**
     2  * 2010-2-26
     3  * 
     4  * 情 缘
     5  * 
     6  * 该类是一个枚举类型,定义了数据库聚合函数
     7  * 操作的各种情况。该枚举值可以在使用时候来
     8  * 区分sql执行那个聚合函数
     9  * 
    10  * */
    11 using System;
    12 using System.Collections.Generic;
    13 using System.Linq;
    14 using System.Text;
    15 
    16 namespace CommonData.Model.Core
    17 {
    18     public enum Converage
    19     {
    20         /// <summary>
    21         /// 聚合函数取最小值
    22         /// </summary>
    23         Min,
    24 
    25         /// <summary>
    26         /// 聚合函数取最大值
    27         /// </summary>
    28         Max,
    29 
    30         /// <summary>
    31         /// 聚合函数取和
    32         /// </summary>
    33         Sum,
    34 
    35         /// <summary>
    36         /// 聚合函数取所有数据行
    37         /// </summary>
    38         Count,
    39 
    40         /// <summary>
    41         /// 聚合函数取所有非空数据行
    42         /// </summary>
    43         CountNotNll,
    44 
    45         /// <summary>
    46         /// 聚合函数取平均值
    47         /// </summary>
    48         Avg,
    49     }
    50 }
    51 

      

    该代码中定义了最和函数取最大值和最小值,聚合函数求和,聚合函数查询行数,聚合函数求平均值。

    下面是聚合函数sql语句生成的代码实现:

    聚合函数sql语句生成的代码实现
     1 /// <summary>
     2         /// 根据实体类型来创建该实体对应数据库表的聚合函数查询sql语句
     3         /// 该方法创建的sql语句主要是用于统计查询(最大值,最小值,求和,平均值,数据行数),
     4         /// 同时该sql是有条件查询的
     5         /// </summary>
     6         /// <param name="type">实体类型</param>
     7         /// <param name="converage">聚合函数枚举类型</param>
     8         /// <param name="propertyName">聚合函数作用的属性名称</param>
     9         /// <param name="dic">查询条件属性键值</param>
    10         /// <param name="component">查询条件组建对象</param>
    11         /// <returns></returns>
    12         public string CreateConverageSql(Type type, Converage converage, string propertyName, IDictionary<stringobject> dic, out IDataParameter[] param, ConditionComponent component)
    13         {
    14             StringBuilder sbValues = new StringBuilder();
    15             if (string.IsNullOrEmpty(propertyName))
    16             {
    17                 converage = Converage.Count;
    18             }
    19             if (Converage.Avg == converage)
    20             {
    21                 sbValues.AppendFormat("select avg({0}) from {1} where 1=1 ", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
    22             }
    23             else if (Converage.Max == converage)
    24             {
    25                 sbValues.AppendFormat("select max({0}) from {1} where 1=1 ", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
    26             }
    27             else if (Converage.Min == converage)
    28             {
    29                 sbValues.AppendFormat("select min({0}) from {1} where 1=1 ", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
    30             }
    31             else
    32             {
    33                 sbValues.AppendFormat("select count(*) from {0} where 1=1 ", EntityTypeCache.GetTableInfo(type).Table.Name);
    34             }
    35 
    36             IList<IDataParameter> listParams = new List<IDataParameter>();
    37             foreach (string key in dic.Keys)
    38             {
    39                 switch (component.DicComponent[key])
    40                 {
    41                     case SearchComponent.Equals:
    42                         sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name, "=", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name);
    43                         break;
    44                     case SearchComponent.UnEquals:
    45                         sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name, "!=", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name);
    46                         break;
    47                     case SearchComponent.Between:
    48                         break;
    49                     case SearchComponent.Greater:
    50                         sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name, ">", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name);
    51                         break;
    52                     case SearchComponent.GreaterOrEquals:
    53                         sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name, ">=", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name);
    54                         break;
    55                     case SearchComponent.GroupBy:
    56                         break;
    57                     case SearchComponent.In:
    58                         break;
    59                     case SearchComponent.Less:
    60                         sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name, "<", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name);
    61                         break;
    62                     case SearchComponent.LessOrEquals:
    63                         sbValues.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name, "<=", EntityTypeCache.GetTableInfo(type).DicColumns[key].Name);
    64                         break;
    65                     case SearchComponent.Like:
    66                         break;
    67                     case SearchComponent.Or:
    68                         break;
    69                     case SearchComponent.OrderAsc:
    70                         break;
    71                     case SearchComponent.OrderDesc:
    72                         break;
    73                 }
    74                 listParams.Add(CreateParameter("@" + EntityTypeCache.GetTableInfo(type).DicColumns[key].Name, dic[key]));
    75             }
    76             param = listParams.ToArray();
    77             return sbValues.ToString();
    78         }

    6.       参数占位符

    在这个生成sql语句的组建方法中,我们不断使用了IDataParameter 这个对象,这个对象或许我们看了很陌生,我们用得非常少.(纠正一下是接口),在查询sql Server 数据的时候我们经常使用的一个类 SqlParameter,看到这两个名称如此相似,我们应该也想到了他们是什么关系。因为我们不确定是使用什么数据库,可能是Sql Server,可能是Oracle,还有肯能是Access,所以使用IDataParameter 是比较保险的一种方式。在这个方法中我们也看到了一个新的类型DataType它定义了数据库中常用25中类型于.net中数据类型的对应列表。

     下面是源码解析:

    数据类型对应枚举列表
      1 /**
      2  * 2010-1-28
      3  * 
      4  * 情 缘
      5  * 
      6  * 用于描述SQL数据库类型和.NET 中数据类型的转化关系
      7  * 注意: 这里的数据类型并不是所有的都能直接转化,有
      8  * 时候需要通过特定的规则进行强制性转化。这里描述的
      9  * 都是SQL Server 数据的类型。
     10  * */
     11 
     12 using System;
     13 
     14 
     15 namespace CommonData.Model.Core
     16 {
     17     public enum DataType
     18     {
     19         /// <summary>
     20         /// 对应.NET中的数据类型 Int64 
     21         /// </summary>
     22         Bigint,            
     23 
     24         /// <summary>
     25         /// 对应.NET中的数据类型 Int32 
     26         /// </summary>
     27         Int,              
     28 
     29         /// <summary>
     30         /// 对应.NET中的数据类型 Int16 
     31         /// </summary>
     32         Smallint,         
     33 
     34         /// <summary>
     35         /// 对应.NET中的数据类型 System.Byte 
     36         /// </summary>
     37         Tinyint,          
     38 
     39         /// <summary>
     40         /// 对应.NET中的数据类型 bool 
     41         /// </summary>
     42         Bit,              
     43 
     44         /// <summary>
     45         /// 对应.NET中的数据类型 System.Decimal 
     46         /// </summary>
     47         Decimal,          
     48 
     49         /// <summary>
     50         /// 对应.NET中的数据类型 System.Decimal 
     51         /// </summary>
     52         Numeric,         
     53 
     54         /// <summary>
     55         /// 对应.NET中的数据类型 System.Decimal 
     56         /// </summary>
     57         Money,             
     58 
     59         /// <summary>
     60         /// 对应.NET中的数据类型 
     61         /// </summary>
     62         Smallmoney,        
     63 
     64         /// <summary>
     65         /// 对应.NET中的数据类型 System.Double 
     66         /// </summary>
     67         Float,            
     68 
     69         /// <summary>
     70         /// 对应.NET中的数据类型 System.Single 
     71         /// </summary>
     72         Real,             
     73 
     74         /// <summary>
     75         /// 对应.NET中的数据类型 System.DateTime 
     76         /// </summary>
     77         Datetime,          
     78 
     79         /// <summary>
     80         /// 对应.NET中的数据类型 System.DateTime 
     81         /// </summary>
     82         Smalldatetime,     
     83 
     84         /// <summary>
     85         /// 对应.NET中的数据类型 String 
     86         /// </summary>
     87         Char,             
     88 
     89         /// <summary>
     90         /// 对应.NET中的数据类型 String 
     91         /// </summary>
     92         Varchar,          
     93 
     94         /// <summary>
     95         /// 对应.NET中的数据类型 String 
     96         /// </summary>
     97         Text,             
     98 
     99         /// <summary>
    100         /// 对应.NET中的数据类型 String 
    101         /// </summary>
    102         Nchar,            
    103 
    104         /// <summary>
    105         /// 对应.NET中的数据类型 String 
    106         /// </summary>
    107         Nvarchar,         
    108 
    109         /// <summary>
    110         /// 对应.NET中的数据类型 String
    111         /// </summary>
    112         Ntext,             
    113  
    114         /// <summary>
    115         /// 对应.NET中的数据类型 System.Byte[] 
    116         /// </summary>
    117         Binary,           
    118 
    119         /// <summary> 
    120         /// 对应.NET中的数据类型 System.Byte[] 
    121         /// </summary>
    122         Varbinary,        
    123 
    124         /// <summary>
    125         /// 对应.NET中的数据类型 System.Byte[] 
    126         /// </summary>
    127         Image,             
    128 
    129         /// <summary>
    130         /// 对应.NET中的数据类型 System.DateTime 
    131         /// </summary>
    132         Timestamp,         
    133 
    134         /// <summary>
    135         /// 对应.NET中的数据类型 System.Guid 
    136         /// </summary>
    137         Uniqueidentifier,  
    138 
    139         /// <summary>
    140         /// 对应.NET中的数据类型 Object 
    141         /// </summary>
    142         Variant           
    143 
    144     }
    145 }
    146 

    以上数据类型都是在程序设计中比较常用的,而且在我们在程序设计的时候,往往都会遇到类型不是完全匹配的时候,在后面的章节中将特殊的讲解一个数据类型与数据类型的不同。在使用CreateParameter() 创建占位符参数的时候,我们也要转化一下类型。之前我们使用SqlParameter 的时候,很多人就是new SqlParameter("@name","qingyuan") 这样对应。就默认为string 类型可以直接转化为sql中的nvarchar,varchar等类型,其实不然。中间还有一个转化过程。

    .net 与SQL 类型的相互转化
     1  /// <summary>
     2         /// 数据库类型的转化
     3         /// </summary>
     4         /// <param name="type">程序中的类型</param>
     5         /// <returns></returns>
     6         private SqlDbType ConvertType(DataType type)
     7         {
     8             SqlDbType sqlType = SqlDbType.BigInt;
     9             switch (type)
    10             {
    11                 case DataType.Bigint:
    12                     sqlType = SqlDbType.BigInt;
    13                     break;
    14                 case DataType.Binary:
    15                     sqlType = SqlDbType.Binary;
    16                     break;
    17                 case DataType.Bit:
    18                     sqlType = SqlDbType.Bit;
    19                     break;
    20                 case DataType.Char:
    21                     sqlType = SqlDbType.Char;
    22                     break;
    23                 case DataType.Datetime:
    24                     sqlType = SqlDbType.DateTime;
    25                     break;
    26                 case DataType.Decimal:
    27                     sqlType = SqlDbType.Decimal;
    28                     break;
    29                 case DataType.Float:
    30                     sqlType = SqlDbType.Float;
    31                     break;
    32                 case DataType.Image:
    33                     sqlType = SqlDbType.Image;
    34                     break;
    35                 case DataType.Int:
    36                     sqlType = SqlDbType.Int;
    37                     break;
    38                 case DataType.Money:
    39                     sqlType = SqlDbType.Money;
    40                     break;
    41                 case DataType.Nchar:
    42                     sqlType = SqlDbType.NChar;
    43                     break;
    44                 case DataType.Ntext:
    45                     sqlType = SqlDbType.NText;
    46                     break;
    47                 case DataType.Numeric:
    48                     sqlType = SqlDbType.Decimal;
    49                     break;
    50                 case DataType.Nvarchar:
    51                     sqlType = SqlDbType.NVarChar;
    52                     break;
    53                 case DataType.Real:
    54                     sqlType = SqlDbType.Float;
    55                     break;
    56                 case DataType.Smalldatetime:
    57                     sqlType = SqlDbType.SmallDateTime;
    58                     break;
    59                 case DataType.Smallint:
    60                     sqlType = SqlDbType.SmallInt;
    61                     break;
    62                 case DataType.Smallmoney:
    63                     sqlType = SqlDbType.SmallMoney;
    64                     break;
    65                 case DataType.Text:
    66                     sqlType = SqlDbType.Text;
    67                     break;
    68                 case DataType.Timestamp:
    69                     sqlType = SqlDbType.Timestamp;
    70                     break;
    71                 case DataType.Tinyint:
    72                     sqlType = SqlDbType.TinyInt;
    73                     break;
    74                 case DataType.Uniqueidentifier:
    75                     sqlType = SqlDbType.UniqueIdentifier;
    76                     break;
    77                 case DataType.Varbinary:
    78                     sqlType = SqlDbType.VarBinary;
    79                     break;
    80                 case DataType.Varchar:
    81                     sqlType = SqlDbType.VarChar;
    82                     break;
    83                 case DataType.Variant:
    84                     sqlType = SqlDbType.Variant;
    85                     break;
    86 
    87             }
    88             return sqlType;
    89         }
    90 

          所以说做程序不能只看到表面现象,只有深入的去了解他们的原理,知识的使用才能游刃有余。即使千变万化,也是万变不离其宗。

         说到这篇文章,我只能说我只写到了很肤浅的一部分。明天要去参加老赵的一个演讲,我想大家都应该这道他的主题是什么了,在文章的结尾我想说,.net 的确有他的奥妙之处。或许我们是觉得.net入门非常简单,这些我承认。说.net 是傻瓜式编程,其实是不是傻瓜式编程这个不是由语言决定的,关键在于你怎么去使用这个东西。C# 的确是一门非常优美的语言,我只能以这种言辞来表达。各种语言编程都有他的好处和坏处,不能从单一角度出发,只有你深入的了解了你就会发现它的美。

    (注: ORM涉及内容比较多,后续期待,有兴趣的可以与本人探讨) 

     

     

  • 相关阅读:
    [Redux-Observable && Unit Testing] Use tests to verify updates to the Redux store (rxjs scheduler)
    [Redux-Observable && Unit Testing] Mocking an ajax request when testing epics
    [Redux-Observable && Unit testing] Testing the output of epics
    [React] Create a queue of Ajax requests with redux-observable and group the results.
    [React] Compound Component (React.Children.map & React.cloneElement)
    [Express] Upload Files with Express
    [Python] List & Object spread in Python
    [Angular & Unit Testing] Testing a RouterOutlet component
    [Angular & Unit Testing] TestBed.get vs Injector
    各司其职的标签
  • 原文地址:https://www.cnblogs.com/qingyuan/p/1713658.html
Copyright © 2020-2023  润新知