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方法。
根据实体属性映射信息生成相关操作的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方法。
分类:
技术类
标签:
NHibernate
, 参数后期绑定
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现