Read only queries Using ADO.NET - c#

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.

Related

Can't store users in the default MVC application

I had some problems with using the authorization before so I got a brand new everything - new computer, new OS, fresh installation of VS, new app and DB in a new resource group on the Azure. The whole shabang.
I can confirm that I can log in to the Azure DB as the screenshots below show.
I can see the databases, tables, users etc.
The problem is that, although it works locally (using the default connection string provided automagically for me), it doesn't perform very well in the Azure (although I'm using the publish file from there). It said something about the file not being found and according to this answer, I needed to change the connection string.
After I've altered it, I get the following error. Please note that the firewall is open and that I can access the DB when I run the code of my applications. I feel that there's something that goes wrong when the authentication part is automatically configured. I'm out of ideas on how to trouble-shoot it, though.
[SqlException (0x80131904): Login failed for user 'Chamster'.
This session has been assigned a tracing ID of '09121235-87f3-4a92-a371-50bc475306ca'. Provide this tracing ID to customer support when you need assistance.]
The connection string I'm using is this.
Server=tcp:f8goq0bvq7.database.windows.net,1433;
Database=Squicker;
User ID=Chamster#f8goq0bvq7;
Password=Abc123();
Encrypt=True;
TrustServerCertificate=False;
Connection Timeout=10;
This issue's bothered me for a while and I'll be bounting it in two days. Any suggestion's warmly appreciated.
I believe I've managed to resolve this weird issue. It appears that the user I'm using, despite being admin with all bells and whistles isn't recognized as admin when used in the connection string and trying to create the tables (which is the case at the first registration).
My solution was to create two logins - one with db_owner role and one with db_datareader and db_datawriter. First, I've used the elevated user in my connection string and registered a single user. That created the tables in the database as shown below.
Then, while able to continue as admin, I realized that we should try the demoted user and tada!, it worked perfectly. Once the tables were there, the whole shabeling behaved as expected.
To be perfectly sure, I dropped the tables from the database and there it was - the same issues as before. When I changed to the elevated user, the tables were restored allowing me to get back to the demoted one.
I also tried dropping the tables, confirming the issues to re-appear and then creating the tables manually. That works too! So basically,the only gotcha that caused it all was the original admin who's not treated as admin.
It might have to do with the fact that my Azure account's getting a bit old, LiveID used there is ancient and that didn't have an updated version of DB in Azure (the pull-up to v12 was carried out the 18th of December, so it's possible that it also was a requirement to get it working). I'm too tired and lazy to check that out and I realize that I've no idea how to get an "old" type of account. Besides, the issue will decrease and gradually vanish because the old accounts get upgraded eventually.

SQL Dependency not working

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

C# creating a database programmatically with SMO

I am trying to create a database, but once created, I cannot connect to it.
The server is Microsoft SQL Server 2008 and using .Net 4.5. We're creating the database with SMO, but we're usually using Dapper to connect and query the database.
This is the code I have so far, which works :
System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connectionString);
Microsoft.SqlServer.Management.Smo.Server srv = new Microsoft.SqlServer.Management.Smo.Server(new Microsoft.SqlServer.Management.Common.ServerConnection(con));
var database = new Microsoft.SqlServer.Management.Smo.Database(srv, dbName);
database.Create(false);
database.Roles["db_datareader"].AddMember(???);
database.Roles["db_datawriter"].AddMember(???);
database.Roles["db_backupoperator"].AddMember(???);
srv.Refresh();
Noce the ??? ? I have tried
System.Environment.UserDomainName + "\\" + System.Environment.UserName
and
System.Environment.UserName
but it fails (update) with the error Add member failed for DatabaseRole 'db_datareader'. with both values.
The problem is that when I create the database, I cannot coonect to it for some reason (using Dapper), from the same program. (update) I get the error message : Cannot open database \"<database_name>\" requested by the login. The login failed.\r\nLogin failed for user '<domain>\\<username>' (where <database_name> is the database name, <domain> my logon domain, and <username> my Windows logon).
Am I missing something? Am I doing th right thing? I've tried searching the web, but it seems no one creates database this way. The methods are there, it should work, no?
** Update **
If I comment the database.Roles["..."].AddMember(...) lines, and I add a break point at srv.Refresh(), resuming the program from there solves everything.
Why a break point solves everything? I can't just break the program in production... nor break the program when creating the database everytime.
It sounds like the Dapper connection issue is a problem with SQL Server doing some of the SMO operations asynchronously. In all likelihood, the new Database is not ready for other users/connections immediately, but requires some small time for SQL Server to prepare it. In "human-time" (in SSMS, or a Breakpoint) this isn't noticeable, but "program-time" it too fast, so you probably need to give it a pause.
This may also be the problem with the Role's AddMember, but there a a number of things that could be wrong here, and we do not have enough information to tell. (specifically, does AddMember work later on? and are the strings being passed correct or not?)
This is happening because you've created the user, but no login for that user. Though I don't know the exact syntax, you're going to have to create a Login. You'll want to set its LoginType to LoginType.WindowsUser. Further, you'll likely need to set the WindowsLoginAccessType to WindowsLoginAccessType.Grant and you'll need to set the Credential by building one, probably a NetworkCredential with the user name you want.
To put a visual on this, the Login is under the Security node for the Server in Management Studio whereas the User is under the Security node for the Database. Both need to exist for access to the SQL Server.

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.

Checking database mirroring status in C#

Our C# application needs to connect to SQL 2005 and 2008 databases and check what the current status of database mirroring is (eg. is it enabled, suspended, paused, disconnected etc). Are there properties where I can check this?
All our databases that are being mirrored have no witness and manual failover (synchronous mirroring).
Much appreciated if anyone can help out or point me to some documentation, google searches are not turning up much on this.
Current state is shown in sys.database_mirroring:
SELECT mirroring_state
FROM sys.database_mirroring
WHERE database_id = DB_ID('...');
The MSDN Article here describes all the System Stored procedures that will give you the information you need
You can also retrieve or update the
current status by running the
sp_dbmmonitorresults system stored
procedure.
One non-obvious difference between using the sp_dbmmonitorresults and using sys.database_mirroring table that's in Remus's answer is the permissions required
Rights needed for sys.database_mirroring
According to the MSDN article Remus referenced
To see the row for a database other
than master or tempdb, you must either
be the database owner or have at least
ALTER ANY DATABASE or VIEW ANY
DATABASE server-level permission or
CREATE DATABASE permission in the
master database. To see non-NULL
values on a mirror database, you must
be a member of the sysadmin fixed
server role
Rights needed for sp_dbmmonitorresults
According to the previous mentioned MSDN article on mirroring SP's
members of the sysadmin fixed server
role, and users who have been added to
the dbm_monitor fixed database role

Categories

Resources