SQL Dependency not working - c#

I am trying to use SQLDependency in my windows application and have followed the steps defined How can I notify my program when the database has been updated? and http://dotnet.dzone.com/articles/c-sqldependency-monitoring
I have enabled Service Broker, set up the queue, created a servie on queue:
ALTER DATABASE [Company] SET ENABLE_BROKER;
CREATE QUEUE ContactChangeMessages;
CREATE SERVICE ContactChangeNotifications
ON QUEUE ContactChangeMessages
([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]);
The next step is to let the SQL user subscribe to the query notifications. I understand I can provide the login user, which is sa (verified using the query SELECT * FROM sys.server_principals):
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO sa;
But I am getting "Cannot find the user 'sa', because it does not exist or you do not have permission."
I have used other users like sysadmin too to grant the permission but every time I was getting the same error. Then I read # http://ask.sqlservercentral.com/questions/7803/msg-15151-level-16-state-1-line-1-cannot-find-the.html) that the permission needs to be provided to a user and not to a login which I did. So now I have provided the permission to 'public' and 'guest' and the sql query executes successfully and not to dbo ("Cannot grant, deny, or revoke permissions to sa, dbo, entity owner, information_schema, sys, or yourself.")
The application code in c# is not too complicated and I have followed the links provided at the beginning so not putting the code here (surely I changed the queue name etc. in line with the sql commands above). But the SQlDependency does not seem to be working when I change the table records (insert/delete).
Where am I going wrong? Is there any step which I am missing

Try:
use [master]
go
alter authorization on database::[YourDatabaseName] to [sa]
go

Related

Error occurs when try to "EXECUTE Master.dbo.xp_CmdShell" commands through web request from database trigger to create text file locally

Requirement: I want to create text file from SQL-Server DB trigger using cmdshell commands(mentioned in title).
Scenarios:
S1:
When I am trying to execute cmdshell command(mentioned in title) from trigger to create text file and write some content in it, it will execute properly and file is getting created.
S2:
When I am trying to call and execute the same scenario S1 from windows Server 2016 WebAPI service through IIS, we are getting following error in Event Viewer.
xp_CmdShell needs a windows account mapping to successfully execute. If you are logged in with a user that has the sysadmin role (I'm guessing this is your first scenario), the account used will be the one for SQL Server Service account.
If the user isn't sysadmin (this should be the IIS user), then it will impersonate the configured account for a special credential called ##xp_cmdshell_proxy_account##, which you need to configure.
To set this account up, use the SP sp_xp_cmdshell_proxy_account, for example:
EXEC sp_xp_cmdshell_proxy_account 'DOMAIN\SQLServerCMDProxy','sdfh%dkc93vcMt0';
You can check this mapping with:
select * from sys.credentials
You will also need to grant the execute command on xp_cmdshell procedure if you didn't already:
GRANT EXEC ON xp_cmdshell TO 'IISUser'
And you can test if it works correctly by impersonating the login with a user with enough priviledges:
EXECUTE AS LOGIN = 'IISUser' -- Shift priviledges to this login for the current session
EXEC xp_cmdshell 'dir *.exe'; -- Try to execute the xp_cmdshell
REVERT -- Revert to the previous login
PD: Be very careful when enabling the use of xp_cmdshell on your SQL Server as it might open security holes, specially when giving permissions to uncontrolled logins. Even if you encapsulate a particular call in an SP, there are workarounds that the user can do to bypass and execute xp_cmdshell directly. The proper way to do this is via certificate signing with a custom login.

Read only queries Using ADO.NET

I want to limit the application to read only queries. In other words, I want the application to process only those queries which are not changing the state of the database. I am using ADO.NET. I do not want to create a new user against the database with read only permissions. Any suggestions are welcome.
Option 1: SQL Authentication
You can use connections as shown below:
Server ={serverName}; Initial Catalog = {DB_Name}; User Id={uid}; Password={pwd};
Use the uid which has only read access in database.
Option 2: Windows Authentication
If you want to use Integrated Security = True; (i.e. windows authentication) then you will have to grant readonly access to the windows user (under which the program runs).
Hope this helps.
You can create triggers to cancel any insert update or delete through a trigger at the database level. The trigger would end with a rollback to cancel the transaction. You would have to figure out who kicked off the trigger so other users can update the db.
I would not do it - I would take away any permission (except select) from the account being used for the application. I have created many, many triggers but I have never heard anyone using database triggers to enforce read only.

A call to "sys.sp_procedure_params_100_managed" system stored procedure in SQL Server doesn't return data for an application role

I have a .NET app which connects to SQL Server 2012 database. The app uses a SQL Server application role which has execute permissions only on the stored procedures in the database. The app uses Enterprise Library which uses the SqlCommandBuilder.DeriveParameters method.
This method calls the [sys].[sp_procedure_params_100_managed] system procedure. The call to this procedure returns no results which is an error and causes EL to give a "Stored procedure xx doesn't exist". XX is the parameter, a procedure name, to the sp_procedure_params_100_managed system procedure to get the input procedure's parameters info. If I do the same call using a user with higher SQL Server privileges, the procedure returns data. So the no data for the application role seems to be a permission/privilege issue.
How does one give proper permissions to a specific system procedure to an application role?
Use Master;
GO
GRANT EXECUTE ON OBJECT::[sys].[sp_procedure_params_100_managed]
TO ApplicationUser; --<-- Whatever the Application Use is called
GO
Use MyDatabase;
GO
GRANT EXECUTE ON OBJECT::[sys].[sp_procedure_params_100_managed]
TO ApplicationUser; --<-- Whatever the Application User is called
GO
Cribbing from M.Ali.
The likely reason for the failure is because you have granted EXECUTE rights on the stored procedures in the DBO schema, where SYS is actually a separate schema. That's difficult to tell without your providing the actual user account configuration though.
use YOURDB;
go
GRANT VIEW DEFINITION TO YOURUSER
-- that worked for me. I was not getting a permissions error - instead, no rows were returned before granting view definition.

Linq Error Service Broker message delivery is not enabled in this database

We have C# LINQ program that writes/reads to a database. We recently moved the database to a different server. I changed the app.config to point to this new server and since then i am getting this error when I do a write to a table. specifically the error occurs on db.SubmitChanges()
"Service Broker message delivery is not enabled in this database. Use the ALTER DATABASE statement to enable Service Broker message delivery."
The same program works fine in the other server with Service Broker message delivery disabled and this is a simple insert into a table. I tried inserting into another test table and that works fine. I can't seem to find a pattern as to when the error occurs either.
You probably already know this stuff from the comment you exchanged with Gert. But...
There is a database option that switches on or off the service broker mechanism.
From mater database, you can check what the settings is on your database (in the same instance)
USE master;
-- Check if it is enabled
SELECT D.is_broker_enabled
FROM sys.databases D
WHERE D.name = 'YourDatabaseName' ;
-- Enable it
ALTER DATABASE YourDatabaseName
SET ENABLE_BROKER
WITH ROLLBACK IMMEDIATE ;
GO
I usually add this to the beginning of the service broker application setup script
USE master;
IF NOT EXISTS
(
SELECT D.is_broker_enabled
FROM sys.databases D
WHERE
D.name = 'YourDatabaseName'
AND D.is_broker_enabled = 1
)
ALTER DATABASE YourDatabaseName
SET ENABLE_BROKER
WITH ROLLBACK IMMEDIATE ;
GO
So I can make sure it gets enabled. But you probably should talk to your DBA because service broker probably eats up some resource in DB engine just by enabling it.

Why does the "drop user" command for SQL not work in C#?

Why does the drop user a_2 command not work when I try to use it in C#, while when I tried it in SQL Server Management Studio, it works there !!???
This is the code that I used it when I create the user & give it a permission:
use DataBaseName;
create login a_2 with password='Aa123';
create user a_2 for login a_2;
grant insert to a_2;
..........
The connection string used :
Data Source=TheServerName;Integrated Security=True;database=master
Note:
I tried to drop a database from C# and it works perfectly without any problem, but when I use it to drop a user the problem raised here !!!
This is the exception that gets raised
Exception is: Cannot drop the user
'a_2', because it does not exist or
you do not have permission.
I believe your problem is that "you do not have permission". Your application is running as a different user from you. You can solve this by either giving the default application user the necessary permissions on the database (not a good idea) or by creating a special user in the database for your application and having the application run as that user.
Be aware that giving your application (or any user, for that matter) permissions to drop users could be very risky if someone figures out how to hack your application. And you aren't actually including the ability to drop the database in your app, are you? Think about it. Instead of creating users in the database, consider creating a Users table just for your application. Then your users won't have such extensive rights to your actual database.
DROP USER would require use DataBaseName;
Or a different connection string
Data Source=TheServerName;Integrated Security=True;database=DataBaseName
That is, the DROP USER only makes sense in the context of your database. When you run it later you are in the context of master = fail.

Categories

Resources