Running a SQL Server 2012 CLR stored procedure with this code:
const string executeLog = "EXEC master..xp_logevent @errorNumber, @message, informational";
using (SqlCommand cmd = new SqlCommand(executeLog, connection))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("@errorNumber", 60001);
cmd.Parameters.AddWithValue("@message", url);
cmd.ExecuteScalar();
}
I get this error:
System.Data.SqlClient.SqlException: The EXECUTE permission was denied
on the object 'xp_logevent', database 'mssqlsystemresource', schema
'sys'.
I've tried to do this as sa
user:
grant execute on xp_logevent to sa
But I get another error:
You can not find user 'sa' that does not exist or the user does not
have permission.
How can I grant execute permissions to sa user?
Best Answer
You don't need to grant execute anything to
sa
assa
is in thesysadmin
server role and can pretty much do anything. Hence, if you are getting an error executingxp_logevent
, then you aren't logging in assa
. Is the connection string usingcontext connection = true;
or a regular / external connection? If usingcontext connection = true;
then the permissions are based on whoever is executing the SQLCLR stored procedure. If using a regular connection, the permissions are based on the logon account for the SQL Server NT Service (MSSQLSERVER / SQLEXPRESS if it is a default instance) by default, else it can be the permissions of whoever is executing the SQLCLR stored procedure if code has been added to do impersonation.So, how is the
SqlConnection
being made? The answer to that question will help determine the appropriate fix. If this SQLCLR stored procedure is to be called by anyone (meaning, Users who are not necessarily in thedb_owner
database role or thesysadmin
server role), then you can do the following to grant this permission to the smallest scope possible.In the database that contains the SQLCLR stored procedure:
db_owner
Database Roledbo.LogEvent
) that accepts the two parameters you are passing in (@errorNumber
and@message
) and simply executesEXEC xp_logevent @errorNumber, @message, informational;
EXECUTE
on this new Stored Procedure to any Users and/or Database Roles that will be calling the SQLCLR Stored Proceduredbo.LogEvent
) instead ofxp_logevent
using
statement to havenew SqlCommand("dbo.LogEvent", connection)
cmd.CommandType = CommandType.Text;
to becmd.CommandType = CommandType.StoredProcedure;
const string executeLog
lineOther notes:
AddWithValue
as there are issues with it. Instead, just create theSqlParameter
with an explicitly set datatype and then add it to theSqlCommand.SqlParameters
collection.ExecuteScalar
if you are not capturing something from a result set. Instead, callExecuteNonQuery