有个关于“《.NET中统一的存储过程调用方法(收藏) 》的具体实现 ”的问题要请教

nilnshen 2005-03-19 11:31:30
原贴在http://www.cnblogs.com/renrenqq/archive/2004/08/04/30143.html

我不知道这个类是如何获得存储过程里面返回参数的。
自己试了下,发现当我的存储过程里面有OUTPUT参数的时候,程序会在
myAdapter.Fill(result.MyDataSet, "Table");
这一行出错。
错误类似 “参数 2: String 类型的“@bname”,Size 属性具有无效大小值: 0”

我尝试:
注释myAdapter.Fill(result.MyDataSet, "Table");这一行
然后在调用函数中用一个IDictionaryEnumerator遍历了SqlResult.ReturnVal这个哈希表,发现输出参数的Key都读出来了,而Value都是空的,说明没有从存储过程取到值。

怪了。。。
...全文
98 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
nilnshen 2005-03-20
  • 打赏
  • 举报
回复
终于解决了,把ProcHelper类的
switch(reader["DATA_TYPE"].ToString().ToUpper())
{
case "NVARCHAR":
myParameter.SqlDbType =SqlDbType.NVarChar;
。。。。。 case "VARCHAR":
myParameter.SqlDbType = SqlDbType.VarChar;
。。。。

改为

switch(reader["DATA_TYPE"].ToString().ToUpper())
{
case "NVARCHAR":
myParameter.SqlDbType =SqlDbType.NVarChar;
myParameter.Size = 4000; case "VARCHAR":
myParameter.SqlDbType = SqlDbType.VarChar;
myParameter.Size = 8000;
。。。。

可能因为返回值没有长度导致出错。
另外,在存储过程里面也要写清楚输出参数的长度,否则会导致只输出第一个字符的问题出现,不知道这是什么缘故,还请高手指教!!
nilnshen 2005-03-20
  • 打赏
  • 举报
回复
新发现就是int类型的OUTPUT正常,唯独涉及到varchar,nvarchar的都不正常!!
nilnshen 2005-03-20
  • 打赏
  • 举报
回复
1。数据层
--没用的,不应该贴上去
CSharpProgrammer 2005-03-19
  • 打赏
  • 举报
回复
多看看Duwamish7.0吧,我认为在NET平台,它应该是利用存储过程的典型.
silentwins 2005-03-19
  • 打赏
  • 举报
回复
up
nilnshen 2005-03-19
  • 打赏
  • 举报
回复
0。改写过的ProcHelper类
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections;

namespace Neverstop.WebModules.Data
{

public class SqlResult
{
public DataSet MyDataSet=new DataSet();
public Hashtable ReturnVal=new Hashtable();
}

//这个类是具体的实现,代码并不复杂,这里我也就不罗嗦了.只需要注意方法的参数是可变参数.

//ConnectionString在创建ProcHelper的时候传入
//ProcedureName和parameter在运行Call方法的时候传入

/**//// <summary>
/// SQLProcHelper 的摘要说明。
/// </summary>
public class ProcHelper
{
//存储过程名
private String procedureName=null;
//连接字符串
private String connectionString=null;

private SqlConnection myConnection=new SqlConnection();
private SqlCommand myCommand=new SqlCommand();
private SqlParameter myParameter=new SqlParameter();

#region 存储过程名
public String ProcedureName
{
get
{
return procedureName;
}
set
{
procedureName=value;
}
}
#endregion


#region 连接字符串
public String ConnectionString
{
get
{
return connectionString;
}
set
{
connectionString=value;
}
}

#endregion

#region 构造函数
public ProcHelper(){}

public ProcHelper(String ConnectionString)
{

connectionString=ConnectionString;
}
#endregion

#region 调用存储过程
public SqlResult Call(string ProcedureName, params object[] parameters)
{
// SqlResult是自己定义的用于保存结果数据集、返回值、传出参数集的类
SqlResult result = new SqlResult();

procedureName = ProcedureName;

// 根据需要定义自己的连接字符串
myConnection = new SqlConnection(ConnectionString);

myCommand = new SqlCommand(this.ProcedureName, myConnection);
myCommand.CommandType = CommandType.StoredProcedure;

SqlDataAdapter myAdapter = new SqlDataAdapter(myCommand);

myConnection.Open();
// 获得和创建存储过程的参数,并且设置好值
GetProcedureParameter(parameters);


myAdapter.Fill(result.MyDataSet, "Table");

// 获得存储过程的传出参数值和名字对,保存在一个Hashtable中
GetOutputValue(result);

// 在这里释放各种资源,断开连接
myAdapter.Dispose();
myCommand.Dispose();
myConnection.Close();
myConnection.Dispose();


return result;
}
#endregion
#region 获得存储过程的参数
private void GetProcedureParameter(params object[] parameters)
{
SqlDataReader reader = null;
try
{
SqlCommand myCommand2 = new SqlCommand();

myCommand2.Connection = this.myConnection;
myCommand2.CommandText = "select PARAMETER_NAME,PARAMETER_MODE,DATA_TYPE from INFORMATION_SCHEMA.PARAMETERS where SPECIFIC_NAME='" +this.ProcedureName+ "' order by ORDINAL_POSITION";

reader = myCommand2.ExecuteReader();


// 创建返回参数
myParameter = new SqlParameter();
myParameter.ParameterName = "@Value";
myParameter.SqlDbType = SqlDbType.Int;
myParameter.Direction = ParameterDirection.ReturnValue;

myCommand.Parameters.Add(myParameter);

int i = 0;
// 创建各个参数,在这个地方可以自动的创建SqlParameter的类型,值,方向等属性
while(reader.Read())
{
myParameter = new SqlParameter();

myParameter.ParameterName = reader["PARAMETER_NAME"].ToString();
myParameter.Direction = reader["PARAMETER_MODE"].ToString()=="IN"?ParameterDirection.Input:ParameterDirection.Output;


switch(reader["DATA_TYPE"].ToString().ToUpper())
{
case "NVARCHAR":
myParameter.SqlDbType =SqlDbType.NVarChar;
if(myParameter.Direction == ParameterDirection.Input)
{
myParameter.Value=(string)parameters[i];
}
break;
case "VARCHAR":
myParameter.SqlDbType = SqlDbType.VarChar;
if(myParameter.Direction == ParameterDirection.Input)
{
myParameter.Value=(string)parameters[i];
}
break;
。。。。。。。。。。。。。。。。。 default:
throw new Exception("不支持的数据类型!");
}
i++;

myCommand.Parameters.Add(myParameter);
}
}
finally
{
reader.Close();
}

}
#endregion

#region 获得返回值参数
private void GetOutputValue(SqlResult result)
{
//遍历所有参数
foreach (SqlParameter para in myCommand.Parameters)
{
//如果是返回参数或者输出参数
if (para.Direction!=ParameterDirection.Input)
{
result.ReturnVal.Add(para.ParameterName,para.Value);
}
}
}



#endregion
}
}

nilnshen 2005-03-19
  • 打赏
  • 举报
回复
//不用到OUTPUT的都是好的,插入,删除等等


1。数据层,继承ProcHelper类
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;

using Neverstop.WebModules;
using Neverstop.WebModules.Data;

namespace Neverstop._DAL
{
/// <summary>
/// product 的摘要说明。
/// </summary>
public class product:ProcHelper
{
public product(string ConnectionString):base(ConnectionString)
{ }
#region 商品详细(根据商品ID) //1.返回Hashtable??? (应该返回SqlResult,然后在业务层生成SqlResult.ReturnVal)

public SqlResult ProductItemDetail()
{
ProcHelper helper = new ProcHelper(ConnectionString);
return helper.Call("product_listdetail",4);

}
#endregion
}
}

2。本来还有业务层现在我把业务层去掉了,在页面中直接调用

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;


using Neverstop.Common.Configuration;

private void Page_Load(object sender, System.EventArgs e)
{
//UNDONE 不知道为何取不出OUTPUT的值
try
{
ProcHelper helper = new ProcHelper(ModuleConfig.GetSettings().ConnectionString);

Neverstop.WebModules.Data.SqlResult result = helper.Call("brandtest");

/* IDictionaryEnumerator myEnumerator = result.ReturnVal.GetEnumerator();
while (myEnumerator.MoveNext())
{
lblname.Text += myEnumerator.Key;
lblname.Text += myEnumerator.Value;
}*/

lblname.Text = (string)result.ReturnVal["@bname"];
}
catch(Exception ex)
{
lbltradeprice.Text = ex.Message;
}


3.存储过程

CREATE PROCEDURE brandtest

(
@bname nvarchar(4000) OUTPUT
)

AS

SELECT

@bname = description
FROM

brand

WHERE

bid = 2
GO

62,074

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧