PDF.NET数据开发框架 之SQL-MAP使用存储过程

简介:

有关SQL-MAP的规范性介绍,请看下面的文章:

PDF.NET(PWMIS数据开发框架)之SQL-MAP目标和规范
 

在SQL-MAP中使用存储过程

1,存储过程的输出参数在SQL MAP 中的使用:

我们先创建一个存储过程CountUser ,它有一个输入参数和一个输出参数:

 

复制代码
  Create   Procedure  CountUser
        
@CountNum   int   output,
        
@Field   varchar ( 10 )
        
AS
        
SELECT   @CountNum = result  FROM  Tb_UserCount  WHERE  Field = @Field   
        
if   @CountNum   is   NULL
             
set   @CountNum =- 1
       
else
           
print   @CountNum
        
SELECT   @CountNum   as   MyCount 
       
return   0
复制代码

 

 

在SQL-MAP文件中生成下面的内容(可以使用工具生成):

 

复制代码
  < Select  CommandName ="GetCountByStroy"  CommandType ="StoredProcedure"  Method =""  Description ="获取统计数据"  ResultClass ="ValueType" >
            
<![CDATA[  
        
CountUser
        
        #
Field :String#
        #
CountNum :Int32,Int32,,Output#
                
        
]]>
        
</ Select >
复制代码


在SQL-MAP的命令类型属性中,请指定 CommandType ="StoredProcedure" 表示查询将使用一个存储过程。

 

注意:在Select,Update,Insert,Delete 配置节中都可以使用 存储过程,这里使用的是Select ,选择何种类型决定于你的存储过程类型。

例如,你的存储过程返回值是一个“行结果集”(存储过程最后一行附近是 Select field1,field2... from table...),那么在SQL-MAP配置节中使用Select;

              存储过程返回值是其它值或者没有返回值,则使用Update,Insert,Delete之一,具体选择那个请根据存储过程的语义来决定。


在要执行的脚本内容中,存储过程的参数紧跟在存储过程的名字之后,可以使用空格或者换行分隔,参数之间使用“逗号”或者换行分隔,请看下面的例子也是合法的:

 

SQL-MAP脚本

 

 

2,使用Decimal类型输出参数的存储过程注意事项:

请看下面的存储过程, @nowsyl 是一个 decimal 类型的输出参数:

 

复制代码
CREATE    procedure   [ dbo ] . [ NBF_GetZhuHeSYL ]
(
 
@zdid   varchar ( 38 ), -- myfundid
  @nowsyl   decimal ( 18 , 4 ) output
)
AS

Select   @nowsyl   =   sum (NowShuhuiyingkui) / sum (NowBenjin)  from  TB_Product_MyFund_Open  where  MyFundID = @zdid

return   1

复制代码

 

在SQL-MAP的DAL程序中,如果直接使用配置文件中命令向 GetZhuHeSYL 的脚本书写方式,存储过程的返回值始终是整数:

 

复制代码
public  System.Object GetZhuHeSYL(String zdid  , ref  Double nowsyl   ) 
    { 
            
// 获取命令信息
            CommandInfo cmdInfo = Mapper.GetCommandInfo( " GetZhuHeSYL " );
            
// 参数赋值,推荐使用该种方式;
            cmdInfo.DataParameters[ 0 ].Value  =  zdid;
            cmdInfo.DataParameters[
1 ].Value  =  nowsyl;
            
// 参数赋值,使用命名方式;
            
// cmdInfo.SetParameterValue("@zdid", zdid);
            
// cmdInfo.SetParameterValue("@nowsyl", nowsyl);
            
// 执行查询
            CurrentDataBase.ExecuteScalar(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText , cmdInfo.DataParameters);
            
nowsyl  =  ( double )cmdInfo.DataParameters[ 1 ].Value;
            
return   null ;
        
//
    } // End Function
复制代码

 

 

注意上面代码“红色”的部分,目前代码生成器不能自动生成处理存储过程参数返回类型参数的代码,这些代码需要你手工添加。

--------------------------------
改进措施:
Decimal 类型是一个特殊的类型,在数据库中你需要指定它的“精度”和“小数位数”,如 Decimal(14,4) 表示精度为14位,小数为4位。
经过测试,我们在ADO.NET的命令参数中,必须将参数的小数位数设置成跟数据库中一样的Decimal类型小数位数,才可以获得正确的返回值,数据的精度可以不一样。
要解决这个问题,我们有两个方案,
(1)在存储过程中使用 real 类型替代 Decimal 类型,在程序中使用 double 类型对应存储过程的参数;
(2)改写SQL-MAP 的命令配置项,改成下面的样子:

 

< Select  CommandName ="GetZhuHeSYL"  CommandType ="StoredProcedure"  Description ="获取组合收益率"  ResultClass ="ValueType" >
<![CDATA[
NBF_GetZhuHeSYL #zdid:String,String,38,Input#,#nowsyl:Double,Decimal,18,Output
,18,4#
]]> </ Select >

 

 


注意上面脚本中的红色部分,这样就为Decimal类型指定了查询参数的精度信息了。
注意:该特性仅仅在PDF.NET 4.0 版本受支持!

3,使用存储过程的返回值

如果你需要明确的使用存储过程的返回值(非“行结果集”),例如获取你自己定义的操作状态,则需要注意一些问题。

我们先看一个存储过程的定义:

 

复制代码
代码
SET  ANSI_NULLS  ON
GO
SET  QUOTED_IDENTIFIER  ON
GO
Create   PROCEDURE   [ dbo ] . [ Batch_SettingReminds ]
    
--  Add the parameters for the stored procedure here
     @WorkNo   varchar ( 38 )
    ,
@CustomerIDCardList   varchar ( max
    ,
@JjdmList   varchar ( max )
    ,
@EventConetent   varchar ( max )
    ,
@Cycle   varchar ( 500 )
    ,
@StartDate   varchar ( 21 )
    ,
@RateTypeList   varchar ( 500 )
    ,
@ModelId   varchar ( 38 )
AS
BEGIN
    
--  SET NOCOUNT ON added to prevent extra result sets from
     --  interfering with SELECT statements.
     SET  NOCOUNT  ON ;
    
declare   @t   table
        (
            
[ StartDate ]   [ datetime ]   NULL ,
            
[ NowYield ]   [ float ]   NULL ,
            
[ FundCode ]   [ varchar ] ( 10 NULL ,
            
[ TradeType ]   [ varchar ] ( 50 NULL ,
            
[ TradeMoneyStart ]   [ float ]   NULL ,
            
[ CustomerIDCard ]   [ varchar ] ( 500 NULL ,
            
[ WorkNo ]   [ varchar ] ( 38 NULL ,
            
[ SettingType ]   [ int ]   NULL ,
            
[ SettingDate ]   [ datetime ]   NULL ,
            
[ SettingState ]   [ int ]   NULL ,
            
[ RemindTypeID ]   [ varchar ] ( 38 NULL ,
            
[ RemindEventID ]   [ varchar ] ( 38 NULL ,
            
[ Rate ]   [ float ]   NULL ,
            
[ zhxgrq ]   [ datetime ]   NULL
        )
    
if ( @ModelId = ' 7886FC2E-5038-4A71-8477-121A207BD70F ' )
    
begin
        
        
insert   into   @t   select   distinct   @StartDate , 0 ,a.name, ' -- ' , 0 ,b.name, @WorkNo , 0 , GETDATE (), 1 , @ModelId
        ,(
select  name  from  dbo.Split(c.name, ' : ' where  id = 1 ) -- KEY
        ,( select  name  from  dbo.Split(c.name, ' : ' where  id = 2 ) -- Value
        , GETDATE ()  from  dbo.Split( @JjdmList , ' , ' )  a  left   join  dbo.Split( @CustomerIDCardList , ' , ' ) b  on   1 = 1   left   join  dbo.Split( @EventConetent , ' , ' ) c  on   1 = 1  
        
        
insert   into   @t   select   distinct   @StartDate , 0 ,a.name, ' -- ' , 0 ,b.name, @WorkNo , 0 , GETDATE (), 1 , @ModelId ,c.name, 0 , GETDATE ()  from  dbo.Split( @JjdmList , ' , ' )  a  left   join  dbo.Split( @CustomerIDCardList , ' , ' ) b  on   1 = 1   left   join  dbo.Split( @Cycle , ' , ' ) c  on   1 = 1  
        
        
insert   into   @t   select   distinct   @StartDate , 0 ,a.name, ' -- ' , 0 ,b.name, @WorkNo , 0 , GETDATE (), 1 , @ModelId
        ,(
select  name  from  dbo.Split(c.name, ' : ' where  id = 1 ) -- KEY
        ,( select  name  from  dbo.Split(c.name, ' : ' where  id = 2 ) -- Value
        , GETDATE ()  from  dbo.Split( @JjdmList , ' , ' )  a  left   join  dbo.Split( @CustomerIDCardList , ' , ' ) b  on   1 = 1   left   join  dbo.Split( @RateTypeList , ' , ' ) c  on   1 = 1  
    
        
        
insert   into   [ WFT_RemindSetting ]   select   NEWID (), *   from   @t     
        
return   @@rowcount
    
end
    
    
    
    
if ( @ModelId = ' 359A80EF-6769-401E-97A8-2EEEAE3C61C7 '
    
begin
        
declare   @t_1   table
        (
            CustomerIDCard 
varchar ( 500 )
            ,JJDM 
varchar ( 10 )
            ,BuyDate 
varchar ( 21 )
        )
        
        
insert   into   @t_1   select  a.name,c.JJDM, @StartDate   from  dbo.Split( @CustomerIDCardList , ' , ' ) a  left   join  WFT_Customer b  on  a.name  = b.CustomerIDcard  left   join  WFT_CustomerFundTrade c  on  b.FundAccount = c.FundAccount  where  c.NowLot > 0
        
if ( @StartDate = ' 1900-01-01 ' )    
        
begin
            
update   @t_1   set  BuyDate =  ( select   top   1   CONVERT ( VARCHAR ,x.TradeDate, 23 from  WFT_CustomerFundTradeDetails x  left   join  WFT_Customer y  on  x.FundAccount = y.FundAccount  where  x.JJDM = JJDM  and  y.CustomerIDcard = CustomerIDcard  and  x.IsHistory = ' 0 '   order   by  x.TradeDate)
            
        
end
        
        
insert   into   @t   select  a.BuyDate, 0 ,a.JJDM, ' -- ' , 0 ,a.CustomerIDCard, @WorkNo , 0 , GETDATE (), 1 , @ModelId
        ,(
select  name  from  dbo.Split(c.name, ' : ' where  id = 1 ) -- KEY
        ,( select  name  from  dbo.Split(c.name, ' : ' where  id = 2 ) -- Value
        , GETDATE ()  from   @t_1   a   left   join  dbo.Split( @RateTypeList , ' , ' ) c  on   1 = 1
        
        
        
insert   into   [ WFT_RemindSetting ]   select   NEWID (), *   from   @t     
        
return   @@rowcount
        
    
end
    
    
if ( @ModelId = ' C9D578B8-17D4-43A8-84B4-EB1BD44D8D9A '
    
begin
        
insert   into   @t   select   distinct   @StartDate , 0 , ' -- ' , ' -- ' , 0 ,b.name, @WorkNo , 0 , GETDATE (), 1 , @ModelId
        ,(
select  name  from  dbo.Split(c.name, ' : ' where  id = 1 ) -- KEY
        ,( select  name  from  dbo.Split(c.name, ' : ' where  id = 2 ) -- Value
        , GETDATE ()  from  dbo.Split( @CustomerIDCardList , ' , ' ) b  left   join  dbo.Split( @RateTypeList , ' , ' ) c  on   1 = 1  
    
        
        
insert   into   @t   select   distinct   @StartDate , 0 , ' -- ' , ' -- ' , 0 ,b.name, @WorkNo , 0 , GETDATE (), 1 , @ModelId
        ,d.name
        ,
0
        ,
GETDATE ()  from  dbo.Split( @CustomerIDCardList , ' , ' ) b  left   join  dbo.Split( @Cycle , ' , ' ) d  on   1 = 1
        
        
        
insert   into   [ WFT_RemindSetting ]   select   NEWID (), *   from   @t
        
return   @@rowcount     
    
end
    
--  Insert statements for procedure here
    
END
复制代码

 

 

这是一个复杂的存储过程,中间有多个Insert 语句,而且在存储过程开头使用了SET NOCOUNT ON 语法,所以存储过程不会返回操作受影响的行数,但是存储过程中已经明确写了下面的返回值语句:

return @@rowcount    

所以我们需要一个“返回值”参数,但这个参数名并没有定义,没关系我们随便用一个名字即可。我们先看看这个存储过程对应的SQL-MAP脚本怎么写:

 

复制代码
< Insert  CommandName ="BatchSettingReminds"  Method =""  CommandType ="StoredProcedure"  Description ="批量插入提醒" >
          
<![CDATA[
          [Batch_SettingReminds]
          #WorkNo:String#,
          #CustomerIDCardList:String#,
          #JjdmList:String#,
          #EventConetent:String#,
          #Cycle:String#,
          #StartDate:String#,
          #RateTypeList:String#,
          #ModelId:String#,
         
 #result:Int32,Int32,,ReturnValue#
          
]]>
      
</ Insert >
 
</ Insert >
复制代码

 

 

请注意参数 result 的定义,它是一个整数类型,存储过程的输出类型是 ReturnValue 。

我们使用代码生成器来生成上面的代码,请注意目前代码生成器还没有这么“智能”的处理这类问题,所以需要你手工修改一下代码:

 ///// <summary>
    ///// 批量插入提醒
    ///// </summary>
    ///// <param name="WorkNo"></param>
    ///// <param name="CustomerIDCardList"></param>
    ///// <param name="JjdmList"></param>
    ///// <param name="EventConetent"></param>
    ///// <param name="Cycle"></param>
    ///// <param name="StartDate"></param>
    ///// <param name="RateTypeList"></param>
    ///// <param name="ModelId"></param>
    ///// <param name="result"></param>
    ///// <returns></returns>
    //public Int32 BatchSettingReminds(String WorkNo  , String CustomerIDCardList  , String JjdmList  , String EventConetent  , String Cycle  , String StartDate  , String RateTypeList  , String ModelId ,int result  ) 
    //{
    //        //获取命令信息
    //        CommandInfo cmdInfo=Mapper.GetCommandInfo("BatchSettingReminds");
    //        //参数赋值,推荐使用该种方式;
    //        cmdInfo.DataParameters[0].Value = WorkNo;
    //        cmdInfo.DataParameters[1].Value = CustomerIDCardList;
    //        cmdInfo.DataParameters[2].Value = JjdmList;
    //        cmdInfo.DataParameters[3].Value = EventConetent;
    //        cmdInfo.DataParameters[4].Value = Cycle;
    //        cmdInfo.DataParameters[5].Value = StartDate;
    //        cmdInfo.DataParameters[6].Value = RateTypeList;
    //        cmdInfo.DataParameters[7].Value = ModelId;
    //        cmdInfo.DataParameters[8].Value = result;
    //        //参数赋值,使用命名方式;
    //        //cmdInfo.SetParameterValue("@WorkNo", WorkNo);
    //        //cmdInfo.SetParameterValue("@CustomerIDCardList", CustomerIDCardList);
    //        //cmdInfo.SetParameterValue("@JjdmList", JjdmList);
    //        //cmdInfo.SetParameterValue("@EventConetent", EventConetent);
    //        //cmdInfo.SetParameterValue("@Cycle", Cycle);
    //        //cmdInfo.SetParameterValue("@StartDate", StartDate);
    //        //cmdInfo.SetParameterValue("@RateTypeList", RateTypeList);
    //        //cmdInfo.SetParameterValue("@ModelId", ModelId);
    //        //cmdInfo.SetParameterValue("@result", result);
    //        return CurrentDataBase.ExecuteNonQuery(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText , cmdInfo.DataParameters);
     //    //
    //}//End Function

 

上面的代码可以正确的执行,但是我们调用方法以后,没有获得结果 result ,因为它是值类型,需要明确标注成引用类型,这里我们修改一下上面代码,让方法直接返回这个result。

 

复制代码
public   partial   class  RemindSettingDAL
    {
        
///   <summary>
        
///  批量插入提醒
        
///   </summary>
        
///   <param name="WorkNo"></param>
        
///   <param name="CustomerIDCardList"></param>
        
///   <param name="JjdmList"></param>
        
///   <param name="EventConetent"></param>
        
///   <param name="Cycle"></param>
        
///   <param name="StartDate"></param>
        
///   <param name="RateTypeList"></param>
        
///   <param name="ModelId"></param>
        
///   <param name="result"></param>
        
///   <returns></returns>
         public  Int32 BatchSettingReminds(String WorkNo, String CustomerIDCardList, String JjdmList, String EventConetent, String Cycle, String StartDate, String RateTypeList, String ModelId)
        {
            
int  result  =   0 ;
            
// 获取命令信息
            CommandInfo cmdInfo  =  Mapper.GetCommandInfo( " BatchSettingReminds " );
            
// 参数赋值,推荐使用该种方式;
            cmdInfo.DataParameters[ 0 ].Value  =  WorkNo;
            cmdInfo.DataParameters[
1 ].Value  =  CustomerIDCardList;
            cmdInfo.DataParameters[
2 ].Value  =  JjdmList;
            cmdInfo.DataParameters[
3 ].Value  =  EventConetent;
            cmdInfo.DataParameters[
4 ].Value  =  Cycle;
            cmdInfo.DataParameters[
5 ].Value  =  StartDate;
            cmdInfo.DataParameters[
6 ].Value  =  RateTypeList;
            cmdInfo.DataParameters[
7 ].Value  =  ModelId;
            cmdInfo.DataParameters[
8 ].Value  =  result; // 这个是返回值参数
             // 参数赋值,使用命名方式;
            
// cmdInfo.SetParameterValue("@WorkNo", WorkNo);
            
// cmdInfo.SetParameterValue("@CustomerIDCardList", CustomerIDCardList);
            
// cmdInfo.SetParameterValue("@JjdmList", JjdmList);
            
// cmdInfo.SetParameterValue("@EventConetent", EventConetent);
            
// cmdInfo.SetParameterValue("@Cycle", Cycle);
            
// cmdInfo.SetParameterValue("@StartDate", StartDate);
            
// cmdInfo.SetParameterValue("@RateTypeList", RateTypeList);
            
// cmdInfo.SetParameterValue("@ModelId", ModelId);
            
// cmdInfo.SetParameterValue("@result", result);
            
// 下面的代码需要手工修改
            
// 执行查询
             int  count  =  CurrentDataBase.ExecuteNonQuery(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText, cmdInfo.DataParameters);
            result 
=  ( int )cmdInfo.DataParameters[ 8 ].Value;
            
return  result;
            
//
        } // End Function
    }
复制代码

 

 

我们使用partial class  类文件方式,可以确保代码生成器不会覆盖了我们手工修改的代码。

这样,存储过程使用返回值参数的问题也解决了。

------------------------------------------------------

到此为止,有关SQL-MAP使用存储过程的问题就解决了,更为基础的示例教程,参看网友

jack_mjl  写的文章

PDF.NET框架学习篇之SQL-MAP使用存储过程

     本文转自深蓝医生博客园博客,原文链接:http://www.cnblogs.com/bluedoctor/archive/2010/07/03/1769890.html,如需转载请自行联系原作者





相关文章
|
4月前
|
SQL XML Java
配置Spring框架以连接SQL Server数据库
最后,需要集成Spring配置到应用中,这通常在 `main`方法或者Spring Boot的应用配置类中通过加载XML配置或使用注解来实现。
434 0
|
6月前
|
存储 SQL 数据库连接
C#程序调用Sql Server存储过程异常处理:调用存储过程后不返回、不抛异常的解决方案
本文分析了C#程序操作Sql Server数据库时偶发的不返回、不抛异常问题,并提出了解决思路。首先解析了一个执行存储过程的函数`ExecuteProcedure`,其功能是调用存储过程并返回影响行数。针对代码执行被阻塞但无异常的情况,文章总结了可能原因,如死锁、无限循环或网络问题等。随后提供了多种解决方案:1) 增加日志定位问题;2) 使用异步操作提升响应性;3) 设置超时机制避免阻塞;4) 利用线程池分离主线程;5) 通过信号量同步线程;6) 监控数据库连接状态确保可用性。这些方法可有效应对数据库操作中的潜在问题,保障程序稳定性。
541 11
|
存储 SQL 数据库
SQL Server存储过程的优缺点
【10月更文挑战第18天】SQL Server 存储过程具有提高性能、增强安全性、代码复用和易于维护等优点。它可以减少编译时间和网络传输开销,通过权限控制和参数验证提升安全性,支持代码共享和复用,并且便于维护和版本管理。然而,存储过程也存在可移植性差、开发和调试复杂、版本管理问题、性能调优困难和依赖数据库服务器等缺点。使用时需根据具体需求权衡利弊。
300 1
|
11月前
|
SQL 安全 Java
除了Flask框架,还有哪些框架能防止SQL注入攻击?
这些框架都在安全方面有着较好的表现,通过它们的内置机制和安全特性,可以有效地降低 SQL 注入攻击的风险。然而,无论使用哪个框架,开发者都需要具备良好的安全意识,正确配置和使用框架提供的安全功能,以确保应用的安全可靠。同时,持续关注安全更新和漏洞修复也是非常重要的。
528 162
|
12月前
|
SQL 监控 安全
Flask 框架防止 SQL 注入攻击的方法
通过综合运用以上多种措施,Flask 框架可以有效地降低 SQL 注入攻击的风险,保障应用的安全稳定运行。同时,持续的安全评估和改进也是确保应用长期安全的重要环节。
486 71
|
8月前
|
SQL 缓存 Java
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
本文详细解构了MyBatis的工作机制,包括解析配置、创建连接、执行SQL、结果封装和关闭连接等步骤。文章还介绍了MyBatis的五大核心功能特性:支持动态SQL、缓存机制(一级和二级缓存)、插件扩展、延迟加载和SQL注解,帮助读者深入了解其高效灵活的设计理念。
|
11月前
|
SQL 存储 人工智能
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
Vanna 是一个开源的 Python RAG(Retrieval-Augmented Generation)框架,能够基于大型语言模型(LLMs)为数据库生成精确的 SQL 查询。Vanna 支持多种 LLMs、向量数据库和 SQL 数据库,提供高准确性查询,同时确保数据库内容安全私密,不外泄。
1637 7
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
|
10月前
|
SQL 分布式计算 Java
Spark SQL向量化执行引擎框架Gluten-Velox在AArch64使能和优化
本文摘自 Arm China的工程师顾煜祺关于“在 Arm 平台上使用 Native 算子库加速 Spark”的分享,主要内容包括以下四个部分: 1.技术背景 2.算子库构成 3.算子操作优化 4.未来工作
1345 0
|
SQL 自然语言处理 数据库
XiYan-SQL:一种多生成器集成的Text-to-SQL框架
XiYan-SQL 是一种创新的多生成器集成Text-to-SQL框架,通过M-Schema增强模型对数据库结构的理解,结合ICL与SFT方法提升SQL生成质量和多样性,经实验证明在多个数据集上表现优异,特别是在Spider和SQL-Eval上取得了领先成绩。
2106 7
|
SQL 安全 PHP
PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全
本文深入探讨了PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全。
611 4