zoukankan      html  css  js  c++  java
  • NHibernate代码解析 SqlCommand SqlString 参数名后绑定

     NHibernate采用参数名后绑定方式。
        根据实体属性映射信息生成相关操作的SQL语句时,并不生成参数名,在SQL字符串层面用一个通配符?表示参数名,在对象层面用SqlCommand目录下的Parameter类表示一个参数。这样有利于中间对SQL语句的的分析和再处理。在SQL语句快要执行之前,NH才生成具体的参数名,填入到SQL 语句之中,并把对应的参数名、参数值赋值到DbParameter对象上。
        为了支持这种处理,相关的几个最基础的类便是SqlCommand目录下的SqlString、SqlStringBuilder、ISqlStringVisitor。
      
        1. SqlString
        代表一个SQL语句字符串。它内部将一个完整的SQL语句切分成一个个独立的部分(parts)进行管理,目的就是支持参数名后绑定。例如SQL语句 SELECT * FROM TableA WHERE Col1=? AND Col2='asdf? asdf' AND Col3=?,在SqlString内部表示为下面四个部分(parts):
    SELECT * FROM TableA WHERE Col1=
    {?}
    AND Col2='asdf? asdf' AND Col3=
    {?}
        每一行表示一个part。part分为两种类型:System.String和NHibernate.SqlCommand.Parameter,上面{?}表示是一个Parameter对象。
        用下面的代码创建一个SqlString对象,调试进去可以查看到上面的结果。
        SqlString sqlstring = SqlString.Parse("SELECT * FROM TableA WHERE Col1=? AND Col2='asdf? asdf' AND Col3=?");
        在NH内部,SqlString只是一个数据格式的承载者,不能通过这个类直接去操作各个part,要创建、重新编辑SqlString对象,使用SqlStringBuilder,要遍历访问各个part,通过ISqlStringVisitor。
        创建SqlString时需要注意:a. SQL语句中不能包含注释  b. 参数以单个?表示  c. 单引里面的字符串值如果包含单引号,应当写成两个单引号才不会有问题。
        2. SqlStringBuilder
        用一个完整的SQL语句创建SqlString对象,可以直接使用SqlString.Parse(string)方法;如果基于多个parts拼装一个 SqlString对象,或者是对已有的SqlString对象重新编辑/拼装,使用SqlStringBuilder。
        SqlStringBuilder的使用者还是得了解SqlString对象的工作模式,严格的按照各个part的顺序使用相应的方法逐个添加。
        对于添加String或者Parameter类型的part,处理很简单;添加一个SqlString,在处理上复杂点,使用一个内嵌类AddingSqlStringVisitor。
        3. ISqlStringVisitor
        通过Visitor模式、SqlStringBuilder类,SqlString类本身的职责变得很单纯:以自己的数据结构表示一个SQL语句,为 ISqlStringVisitor实现者提供访问自己的方法。SqlString对象的Visit方法中按照顺序遍历各个part,把part传给 ISqlStringVisitor相关方法。
        ISqlStringVisitor的实现者AddingSqlStringVisitor将各个part添加到拥有者SqlStringBuilder 中,从而实现在SqlStringBuilder中把SqlString的各个part添加进来。而访问者SqlStringFormatter的主要目的是将SqlString中的Parameter对象生成参数名,从而得到最终可执行的SQL语句。

        4. 参数名后绑定
        根据各种映射信息来构造SQL语句时,统一的使用一个?或者Parameter对象,有利于构造、编辑处理中对参数的识别。使用这种方式处理,就只能按照约定的命名规则来生成参数、操作参数,从DriverBase的ToParameterName(int index)方法可以看到,就是用前缀p+参数位置索引来生成参数名。
        参数名后绑定的实现,查看DriverBase的SetCommandText方法。
  • 相关阅读:
    POJ1470 Closest Common Ancestors(LCA入门)
    POJ1330 Nearest Common Ancestors(倍增LCA算法求无边权树的模板)
    HDU3078 Network (倍增LCA算法求树链)
    HDU2874 Connections between cities(并查集+倍增LCA算法求森林最短路)
    HDU2586 How far away?(倍增LCA算法求带边权树上最短路)
    POJ1062 昂贵的聘礼
    HDU4725 The Shortest Path in Nya Graph(堆优化的dijkstra算法)
    数据仓库详解:包括概念、架构及设计
    利用行为标签构建用户画像
    Spark SQL深度理解篇:模块实现、代码结构及执行流程总览(2)
  • 原文地址:https://www.cnblogs.com/zjoch/p/1311736.html
Copyright © 2011-2022 走看看