tipo tiene ser salida recuperar puede proporcionado procedimiento parámetros parámetro parametros parametro net han ejemplos data consulta con commandtype argumentos .net sql-server stored-procedures

.net - tiene - sqlcommand parameters vb net



El procedimiento espera el parámetro que no se suministró (10)

Recibo el error al acceder a un procedimiento almacenado en SQL Server

Server Error in ''/'' Application. Procedure or function ''ColumnSeek'' expects parameter ''@template'', which was not supplied.

Esto sucede cuando llamo a un Procedimiento almacenado con un parámetro a través de la conexión de datos de .net a sql (System.data.SqlClient) , aunque estoy suministrando el parámetro. Aquí está mi código.

SqlConnection sqlConn = new SqlConnection(connPath); sqlConn.Open(); //METADATA RETRIEVAL string sqlCommString = "QCApp.dbo.ColumnSeek"; SqlCommand metaDataComm = new SqlCommand(sqlCommString, sqlConn); metaDataComm.CommandType = CommandType.StoredProcedure; SqlParameter sp = metaDataComm.Parameters.Add("@template",SqlDbType.VarChar,50); sp.Value = Template; SqlDataReader metadr = metaDataComm.ExecuteReader();

Y mi procedimiento almacenado es:

USE [QCApp] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[ColumnSeek] @template varchar(50) AS EXEC(''SELECT Column_Name, Data_Type FROM [QCApp].[INFORMATION_SCHEMA].[COLUMNS] WHERE TABLE_NAME = '' + @template);

Estoy tratando de descubrir qué estoy haciendo mal aquí.

Editar: Resultó que la Plantilla era nula porque estaba obteniendo su valor de un parámetro pasado a través de la URL y arruiné el paso del parámetro url (estaba usando @ para y en lugar de & )


Además de las otras respuestas aquí, si te olvidaste de poner:

cmd.CommandType = CommandType.StoredProcedure;

Entonces también obtendrás este error.


Este problema generalmente se produce al establecer un valor de parámetro nulo como HLGEM mencionado anteriormente. Pensé que elaboraría algunas soluciones a este problema que he encontrado útiles para el beneficio de personas nuevas en este problema.

La solución que prefiero es establecer por defecto los parámetros del procedimiento almacenado en NULL (o el valor que desee), que fue mencionado por sangram anteriormente, pero puede perderse porque la respuesta es muy detallada. Algo como:

CREATE PROCEDURE GetEmployeeDetails @DateOfBirth DATETIME = NULL, @Surname VARCHAR(20), @GenderCode INT = NULL, AS

Esto significa que si el parámetro termina siendo configurado en el código para anular bajo ciertas condiciones, .NET no establecerá el parámetro y el procedimiento almacenado usará el valor predeterminado que ha definido. Otra solución, si realmente quiere resolver el problema en código, sería usar un método de extensión que maneje el problema, algo así como:

public static SqlParameter AddParameter<T>(this SqlParameterCollection parameters, string parameterName, T value) where T : class { return value == null ? parameters.AddWithValue(parameterName, DBNull.Value) : parameters.AddWithValue(parameterName, value); }

Matt Hamilton tiene una buena publicación here que enumera algunos métodos de extensión más grandes cuando se trata de esta área.


Me encontré con este error hoy cuando se pasaron valores nulos a los parámetros de mi procedimiento almacenado. Pude solucionarlo fácilmente alterando el procedimiento almacenado agregando valor predeterminado = nulo.


Me encuentro con un problema similar al llamar al procedimiento almacenado

CREATE PROCEDURE UserPreference_Search @UserPreferencesId int, @SpecialOfferMails char(1), @NewsLetters char(1), @UserLoginId int, @Currency varchar(50) AS DECLARE @QueryString nvarchar(4000) SET @QueryString = ''SELECT UserPreferencesId,SpecialOfferMails,NewsLetters,UserLoginId,Currency FROM UserPreference'' IF(@UserPreferencesId IS NOT NULL) BEGIN SET @QueryString = @QueryString + '' WHERE UserPreferencesId = @DummyUserPreferencesId''; END IF(@SpecialOfferMails IS NOT NULL) BEGIN SET @QueryString = @QueryString + '' WHERE SpecialOfferMails = @DummySpecialOfferMails''; END IF(@NewsLetters IS NOT NULL) BEGIN SET @QueryString = @QueryString + '' WHERE NewsLetters = @DummyNewsLetters''; END IF(@UserLoginId IS NOT NULL) BEGIN SET @QueryString = @QueryString + '' WHERE UserLoginId = @DummyUserLoginId''; END IF(@Currency IS NOT NULL) BEGIN SET @QueryString = @QueryString + '' WHERE Currency = @DummyCurrency''; END EXECUTE SP_EXECUTESQL @QueryString ,N''@DummyUserPreferencesId int, @DummySpecialOfferMails char(1), @DummyNewsLetters char(1), @DummyUserLoginId int, @DummyCurrency varchar(50)'' ,@DummyUserPreferencesId=@UserPreferencesId ,@DummySpecialOfferMails=@SpecialOfferMails ,@DummyNewsLetters=@NewsLetters ,@DummyUserLoginId=@UserLoginId ,@DummyCurrency=@Currency;

Que construyendo dinámicamente la consulta para búsqueda estaba llamando arriba por:

public DataSet Search(int? AccessRightId, int? RoleId, int? ModuleId, char? CanAdd, char? CanEdit, char? CanDelete, DateTime? CreatedDatetime, DateTime? LastAccessDatetime, char? Deleted) { dbManager.ConnectionString = ConfigurationManager.ConnectionStrings["MSSQL"].ToString(); DataSet ds = new DataSet(); try { dbManager.Open(); dbManager.CreateParameters(9); dbManager.AddParameters(0, "@AccessRightId", AccessRightId, ParameterDirection.Input); dbManager.AddParameters(1, "@RoleId", RoleId, ParameterDirection.Input); dbManager.AddParameters(2, "@ModuleId", ModuleId, ParameterDirection.Input); dbManager.AddParameters(3, "@CanAdd", CanAdd, ParameterDirection.Input); dbManager.AddParameters(4, "@CanEdit", CanEdit, ParameterDirection.Input); dbManager.AddParameters(5, "@CanDelete", CanDelete, ParameterDirection.Input); dbManager.AddParameters(6, "@CreatedDatetime", CreatedDatetime, ParameterDirection.Input); dbManager.AddParameters(7, "@LastAccessDatetime", LastAccessDatetime, ParameterDirection.Input); dbManager.AddParameters(8, "@Deleted", Deleted, ParameterDirection.Input); ds = dbManager.ExecuteDataSet(CommandType.StoredProcedure, "AccessRight_Search"); return ds; } catch (Exception ex) { } finally { dbManager.Dispose(); } return ds; }

Luego, después de rasparme la cabeza, modifiqué el procedimiento almacenado para:

ALTER PROCEDURE [dbo].[AccessRight_Search] @AccessRightId int=null, @RoleId int=null, @ModuleId int=null, @CanAdd char(1)=null, @CanEdit char(1)=null, @CanDelete char(1)=null, @CreatedDatetime datetime=null, @LastAccessDatetime datetime=null, @Deleted char(1)=null AS DECLARE @QueryString nvarchar(4000) DECLARE @HasWhere bit SET @HasWhere=0 SET @QueryString = ''SELECT a.AccessRightId, a.RoleId,a.ModuleId, a.CanAdd, a.CanEdit, a.CanDelete, a.CreatedDatetime, a.LastAccessDatetime, a.Deleted, b.RoleName, c.ModuleName FROM AccessRight a, Role b, Module c WHERE a.RoleId = b.RoleId AND a.ModuleId = c.ModuleId'' SET @HasWhere=1; IF(@AccessRightId IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.AccessRightId = @DummyAccessRightId''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.AccessRightId = @DummyAccessRightId''; END IF(@RoleId IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.RoleId = @DummyRoleId''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.RoleId = @DummyRoleId''; END IF(@ModuleId IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.ModuleId = @DummyModuleId''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.ModuleId = @DummyModuleId''; END IF(@CanAdd IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.CanAdd = @DummyCanAdd''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.CanAdd = @DummyCanAdd''; END IF(@CanEdit IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.CanEdit = @DummyCanEdit''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.CanEdit = @DummyCanEdit''; END IF(@CanDelete IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.CanDelete = @DummyCanDelete''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.CanDelete = @DummyCanDelete''; END IF(@CreatedDatetime IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.CreatedDatetime = @DummyCreatedDatetime''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.CreatedDatetime = @DummyCreatedDatetime''; END IF(@LastAccessDatetime IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.LastAccessDatetime = @DummyLastAccessDatetime''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.LastAccessDatetime = @DummyLastAccessDatetime''; END IF(@Deleted IS NOT NULL) BEGIN IF(@HasWhere=0) BEGIN SET @QueryString = @QueryString + '' WHERE a.Deleted = @DummyDeleted''; SET @HasWhere=1; END ELSE SET @QueryString = @QueryString + '' AND a.Deleted = @DummyDeleted''; END PRINT @QueryString EXECUTE SP_EXECUTESQL @QueryString ,N''@DummyAccessRightId int, @DummyRoleId int, @DummyModuleId int, @DummyCanAdd char(1), @DummyCanEdit char(1), @DummyCanDelete char(1), @DummyCreatedDatetime datetime, @DummyLastAccessDatetime datetime, @DummyDeleted char(1)'' ,@DummyAccessRightId=@AccessRightId ,@DummyRoleId=@RoleId ,@DummyModuleId=@ModuleId ,@DummyCanAdd=@CanAdd ,@DummyCanEdit=@CanEdit ,@DummyCanDelete=@CanDelete ,@DummyCreatedDatetime=@CreatedDatetime ,@DummyLastAccessDatetime=@LastAccessDatetime ,@DummyDeleted=@Deleted;

AQUÍ Estoy inicializando los parámetros de entrada del procedimiento almacenado para anular como sigue

@AccessRightId int=null, @RoleId int=null, @ModuleId int=null, @CanAdd char(1)=null, @CanEdit char(1)=null, @CanDelete char(1)=null, @CreatedDatetime datetime=null, @LastAccessDatetime datetime=null, @Deleted char(1)=null

eso hizo el truco para Mí.

Espero que esto sea útil para alguien que cae en una trampa similar.


Para mi caso, tuve que pasar DBNULL.Value (usando if else else) del código para los parámetros de procedimientos almacenados que no están definidos null pero el valor es null .


Primero, ¿por qué es eso un EXEC? ¿No debería ser eso solo?

AS SELECT Column_Name, ... FROM ... WHERE TABLE_NAME = @template

El SP actual no tiene sentido? En particular, eso buscaría una columna que coincida con @template, no con el valor varchar de @template. es decir, si @template es ''Column_Name'' , buscará WHERE TABLE_NAME = Column_Name , lo cual es muy raro (para que la tabla y la columna tengan el mismo nombre).

Además, si tiene que usar SQL dinámico, debe usar EXEC sp_ExecuteSQL (manteniendo los valores como parámetros) para evitar los ataques de inyección (en lugar de la concatenación de la entrada). Pero no es necesario en este caso.

Re el problema real - se ve bien de un vistazo; ¿Estás seguro de que no tienes una copia diferente del SP dando vueltas? Es un error común...


Si Template no está configurado (es decir, == null), este error se generará también.

Más comentarios:

Si conoce el valor del parámetro cuando agrega parámetros, también puede usar AddWithValue

El EXEC no es obligatorio. Puede hacer referencia al parámetro @template en SELECT directamente.


Tuve el mismo problema, para resolverlo simplemente agregue exactamente el mismo nombre de parámetro a su colección de parámetros como en sus procedimientos almacenados.

Ejemplo

Supongamos que crea un procedimiento almacenado:

create procedure up_select_employe_by_ID (@ID int) as select * from employe_t where employeID = @ID

Así que asegúrese de nombrar su parámetro exactamente como está en su procedimiento almacenado, esto sería

cmd.parameter.add("@ID", sqltype,size).value = @ID

si vas

cmd.parameter.add("@employeID", sqltype,size).value = @employeid

entonces el error sucede.


Tuve un problema donde obtendría el error cuando proporcioné 0 a un parámetro entero. Y descubrió que:

cmd.Parameters.AddWithValue("@Status", 0);

funciona, pero esto no:

cmd.Parameters.Add(new SqlParameter("@Status", 0));


Verificaría mi código de aplicación y vería a qué valor está estableciendo @template. Sospecho que es nulo y ahí radica el problema.