问题描述
DimconnAsSqlConnectionDimcmdAsSqlCommandDimmyReaderAsSqlDataReaderDimmyPrmAsSqlParameter()DimlngRowsAsLongDimlngErrCodeAsLongDimiAsInteger,jAsIntegerconn=NewSqlConnection(connDbStr)conn.Open()cmd=NewSqlCommand("test",conn)Withcmd.CommandType=CommandType.StoredProcedure.CommandTimeout=0.Connection=conn.Parameters.Add("@v",SqlDbType.Int).Value=1.Parameters.Add("@lngErrCode",SqlDbType.Int).Parameters("@lngErrCode").Direction=ParameterDirection.Output.Parameters.Add("@Rows",SqlDbType.Int).Parameters("@Rows").Direction=ParameterDirection.OutputEndWith----------------------------------------------------------------上面代码表示打开SQLSERVER的一个存储过程test,三个参数:@v,@lngErrCode和@Rows,其中@lngErrCode和@Rows需要返回值目的:我想要该存储过程将返回一个纪录集和两个参数@lngErrCode和@Rows,看下面代码:'-------返回值-----------------------------i=cmd.ExecuteNonQuerylngErrCode=cmd.Parameters("@lngErrCode").ValuelngRows=cmd.Parameters("@Rows").Value'-------获取数据集----------------------------myReader=cmd.ExecuteReader()myReader.Read()……现在的问题是:i=cmd.ExecuteNonQuery和myReader=cmd.ExecuteReader()不是要两次打开数据库吗?能不能打开一次数据就把参数返回值和纪录集都抓取过来呢?这在VB6时代不是问题,但在VB.net中我不知怎么写了,兄弟们帮忙看看
解决方案
解决方案二:
cmd.Parameters有类型啊,分input和output你把结果output出来啊,而不是存储过程将结果写入临时表,然后再去临时表里查询
解决方案三:
下面是我数据库端存储过程代码:-------------------------------------------------------CREATEPROCEDURE[dbo].[TEST]@vINT,@lngErrCodeINT=NULLOUTPUT,@RowsINT=NULLOUTPUT-----------------------------------------------------------------WITHENCRYPTIONASSETNOCOUNTONDECLARE@SQLNVARCHAR(MAX)IF@v=1BEGINSELECT@lngErrCode=0SET@SQL=N'SELECT*FROMemployee'+N'SET@Rows=@@ROWCOUNT'--PRINT@SQLEXECSP_EXECUTESQL@SQL,N'@RowsINTOUTPUT',@RowsOUTPUTIF@@ERROR<>0SET@lngErrCode=1END-------------------------------------------------------------------------目的就是:1、返回前台应用程序参数:@lngErrCode和@Rows的值2、返回SELECT*FROMemployee'
解决方案四:
只需要myReader=cmd.ExecuteReader()就可以了i=cmd.ExecuteNonQuery会忽略返回的数据集
解决方案五:
引用3楼dongxinxi的回复:
只需要myReader=cmd.ExecuteReader()就可以了i=cmd.ExecuteNonQuery会忽略返回的数据集
经测试,如果没有cmd.ExecuteNonQuery,那么就得不到@Rows的返回值我既想要纪录集,也同时想得到参数的返回值,怎么办?
解决方案六:
myReader.HasRows和myReader.Read()都能知道有没有记录。myReader.Read()遍历一遍就知道记录数了,为什么要ExecuteNonQuery?
解决方案七:
这应该是由于SqlReader的特殊机制导致的,它是保持连接,连接向后读取的,而不是像datatset那样直接填充到内存表两个办法:改成用sqlAdapter.Fill(dataSet)或者改存储过程说实施,个人比较反感存储过程中用EXECSP_EXECUTESQL执行,容易产生注入bugBEGINSELECT*FROMemployee--也可以返回两个结果集,用dataset获取结果--SELECT@@ROWCOUNTASROWS,CASEWHEN@@ERROR=0THEN0ELSE1ENDASlngErrCodeSET@Rows=@@ROWCOUNTIF@@ERROR<>0SET@lngErrCode=1ElseSET@lngErrCode=0EndEND
解决方案八:
引用5楼Tiger_Zhao的回复:
myReader.HasRows和myReader.Read()都能知道有没有记录。myReader.Read()遍历一遍就知道记录数了,为什么要ExecuteNonQuery?
不仅仅是纪录数的问题,我只是打个比方。我的意思是,我希望一次性将存储过程里的纪录集和参数都返回到前台(假设该存储过程既执行了一个查询,同时又产生了多个OUTPUT类型的参数返回值)。这种情况下,前台采用SqlDataReader方式获取数据好象有问题,它只能抓取纪录集,但不能抓取参数返回值,如果要想抓取参数返回值,还必须得cmd.ExecuteNonQuery,这样一来,不就是两次打开数据库了吗?效率低。
解决方案九:
只要ExecuteReader()就可以。myReader=cmd.ExecuteReader()WhilemyReader.Read()...EndWhilemyReader.Close()'注:必须在SqlDataReader.Close()后才能取OUTPUT参数lngErrCode=cmd.Parameters("@lngErrCode").ValuelngRows=cmd.Parameters("@Rows").Value
解决方案十:
引用8楼Tiger_Zhao的回复:
只要ExecuteReader()就可以。myReader=cmd.ExecuteReader()WhilemyReader.Read()...EndWhilemyReader.Close()'注:必须在SqlDataReader.Close()后才能取OUTPUT参数lngErrCode=cmd.Parameters("@lngErrCode").ValuelngRows=cmd.Parameters("@Rows").Value
这样会有个问题,@Rows(即纪录集行数)在WhilemyReader.Read()...EndWhile时还没被赋值,无法把纪录集作为数组回传。当然可以用遍历myReader的方法来得到这个值,但这毕竟又多了一道开销,也失去了在数据库里返回@Rows的意义如果能够在WhilemyReader.Read()之前就得到@Rows,目的就可以达到了,兄弟们再帮忙看看
解决方案十一:
说人话!!!如果要返回记录集,必定要遍历Reader。不遍历哪来的记录集?
解决方案十二:
引用10楼Tiger_Zhao的回复:
说人话!!!如果要返回记录集,必定要遍历Reader。不遍历哪来的记录集?
文明点,兄弟我是要把纪录集通过数组的方式返还给前台,在把纪录集赋给数组之前不先得REDIM数组吗?你不知道纪录集行数你怎么REDIM数组?要想获得纪录集行数无非两个方法:本地遍历Reader累加获得或者直接把远程数据库端取数时产生的@@ROWCOUNT以OUTPUT参数形式直接获得。我就是不想采用本地遍历Reader累加获得这种效率低的方法才针对第二种方法提出问题。这在VB6中根本就不是问题,我都是这么做的。现在我是想在VB.NET中重写一下,我想在VB6中能做的,没理由在VB.NET中反而不能实现了吧?只是我不熟悉VB.NET的语法,不知道怎样写而已。不懂不要紧,没人怪你,看别人怎样回答就是了,不要做喷子。
解决方案十三:
VB6中记录集是RecordSet,转VB.Net最接近的是DataTable。你的DataTable在哪里?口口声声要按VB6的方式做,转出来的却完全不对应!我们生活在不同的次元,这里逻辑没法沟通了。你觉得这是你那个次元的人话,我无话可说。END
解决方案十四:
不要满脑子数组你查询数据库为什么要放数组里?放list<string>里也比放string[]里要强的多啊
解决方案十五:
引用13楼Z65443344的回复:
不要满脑子数组你查询数据库为什么要放数组里?放list<string>里也比放string[]里要强的多啊
你说的当然有道理啊,但那是另外一个问题。我现在是要对以前的一个VB6程序做升级,只能是数组。这只是就事论事而已。
解决方案:
你不就是要一个返回的记录行数吧:DimTAsNewDataTablemyReader=cmd.ExecuteReader()T.Load(myReader)'T.rows.count是你要的记录行数