¿Cómo puedo capturar un Procedimiento Almacenado de SQL Error provocado por RAISEERROR() en .asmx archivo?
-
12-09-2019 - |
Pregunta
Estoy muy nuevo .NET.Todo lo que he hecho hasta ahora es aplicar algún Procedimiento Almacenado de SQL llamadas como WebServices con copiar y pegar el código existente (como se ha indicado por parte de mi superior).
Estoy llamando a algunos comandos a través de Database.ExecuteNonQuery()
.En el Procedimiento Almacenado de SQL, estoy realizando algunas comprobaciones de seguridad basado en el nombre de usuario que pasó (un usuario sólo puede editar los elementos de los que es propietario).Si la comprobación de seguridad falla, yo estoy llamando RAISEERROR() para desencadenar un error, pero mi .asmx archivo no está viendo esto como una excepción, y simplemente se sale del Procedimiento Almacenado.
Mi asmx archivo:
[WebMethod]
public XmlDocument UpdateSomeItem(Int32 ItemIdNmb, String Foo)
{
try
{
// Create the Database object, using the default database service. The
// default database service is determined through configuration.
Database db = DatabaseFactory.CreateDatabase();
DbParameter param;
string sqlCommand = "updateSomeItem";
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
db.AddInParameter(dbCommand, "ItemIdNmb", DbType.Int32, ItemIdNmb);
db.AddInParameter(dbCommand, "Foo", DbType.String, Foo);
db.AddInParameter(dbCommand, "UpdateLoginIdNmb", DbType.Int32, SessionLoginIdNmb);
#region Return Parameter
param = dbCommand.CreateParameter();
param.ParameterName = "Return";
param.Direction = ParameterDirection.ReturnValue;
param.DbType = DbType.Int32;
dbCommand.Parameters.Add(param);
#endregion
// Execute the Command
db.ExecuteNonQuery(dbCommand);
myDataSet = new DataSet();
myDataSet.DataSetName = "DataSet";
myDataSet.Tables.Add(errorDataTable);
statusDataRow["Status"] = "Success";
statusDataTable.Rows.Add(statusDataRow);
myDataSet.Tables.Add(statusDataTable);
returncodeDataRow["ReturnCode"] = dbCommand.Parameters["Return"].Value;
returncodeDataTable.Rows.Add(returncodeDataRow);
myDataSet.Tables.Add(returncodeDataTable);
xmlReturnDoc.LoadXml(myDataSet.GetXml());
return xmlReturnDoc;
}
// THIS IS WHERE I WANT MY RAISE ERROR TO GO
catch (Exception e)
{
return ReturnClientError(e, "someerror");
}
}
Mi Procedimiento Almacenado de SQL:
CREATE PROCEDURE updateSomeItem
(
@ItemIdNmb INT,
@Foo VARCHAR(100),
@UpdateLoginIdNmb INT
)
AS
SET NOCOUNT ON
/* If the user performing the action did not create the Item in question,
raise an error. */
IF NOT EXISTS
(
SELECT 1
FROM Items
WHERE IdNmb = @ItemIdNmb
AND LoginIdNmb = @UpdateLoginIdNmb
)
RAISERROR (
'User action not allowed - User is not the owner of the specified Item',
10,
1)
UPDATE Items
SET Foo = @Foo
WHERE IdNmb = @ItemIdNmb
RETURN 0
SET NOCOUNT OFF
GO
Solución 2
He actualizado mi procedimiento almacenado con lo siguiente:
/* If the user performing the action did not create the Item in question,
return a code other than 0. */
IF NOT EXISTS
(
SELECT 1
FROM Items
WHERE IdNmb = @ItemIdNmb
AND LoginIdNmb = @UpdateLoginIdNmb
)
RETURN 1
Y que manejo en mi archivo .asmx como esto:
int returnValue = (int)dbCommand.Parameters["Return"].Value;
if (returnValue == 0)
statusDataRow["Status"] = "Success";
/* Stored Procedure will return a value of "1" if the user is
attempting to update an Item that they do not own. */
else
statusDataRow["Status"] = "Error";
statusDataTable.Rows.Add(statusDataRow);
myDataSet.Tables.Add(statusDataTable);
returncodeDataRow["ReturnCode"] = dbCommand.Parameters["Return"].Value;
returncodeDataTable.Rows.Add(returncodeDataRow);
myDataSet.Tables.Add(returncodeDataTable);
Otros consejos
El problema es que el error Gravedad demasiado bajo. Severidades 1 -. 10 se tratan como mensajes de información y no se rompen el flujo de una aplicación de C #
una explicación más detallada se puede encontrar en una responder de Remus Ruşanu .