How to create a Database user in Entity Framework - sql-server

Been working on my first Entity Framework project. As part of the project I am going to be creating a number of SSRS reports. In order to connect to the database I need to have a Reports user that will only access to the specific database on the server. In the past i have always written a script to add Database users but I want to know is there a way that i can do this using Entity Framework instead?

Assuming your user already has a login defined at the SQL Server level (Security > Logins), you can call the following method from your DB initializer seed method to add the user to the database:
private void AddDbUser(MyDataContext myDB)
{
string accountDomainName = "AccountDomainName"; // replace with user's login domain
string accountLoginID = "AccountLoginID"; // replace with user's login ID
string sql =
"USE [MyDB]" +
"CREATE USER [MyNewUser] FOR LOGIN [" + accountDomainName + "\\" + accountLoginID + "]" +
"ALTER AUTHORIZATION ON SCHEMA::[db_datareader] TO [" + accountLoginID + "]" +
"ALTER AUTHORIZATION ON SCHEMA::[db_datawriter] TO [" + accountLoginID + "]" +
"EXEC sp_addrolemember N'db_datawriter', N'" + accountLoginID + "'" +
"EXEC sp_addrolemember N'db_datareader', N'" + accountLoginID + "'";
myDB.Database.ExecuteSqlCommand(sql);
}
The exact SQL needed is dependent on your configuration. To have SQL Server generate the SQL for your scenario, you could open the add user dialog in SSMS (Database > Users > New User...), fill out the fields, and click the "Script" button at the top instead of hitting OK at the bottom. Note that any "GO" lines will need to be removed from the generated script before pasting it into the method above.

You would need to tell EF to use the appropriate stored procedures to do so. You could also wrap these up in a sproc of your own that wraps the relevant commands. There is no native "CreateReportsUser" type method within EF that I know of.
Edit: I probably should have provided this reference to be a "complete" answer. Apologies.
Here's how you can do what I recommend: How to call Stored Procedure in Entity Framework 6 (Code-First)?

Related

Adding a Database User for each Customer

I'm creating a database that has two main parts: a front end which the customer sees and a backend that only the company can see.
It is an email subscriber system so I want the customer to be able to view, add, edit and delete their entries in the email subscriber table, but all the admin-related tables should be hidden from them.
As I'm fairly new to SQL Server 2017, I'm still getting my head around logins, users and roles.
The main question I wanted to ask is what is the best way of doing this? I know I can manually set up database users and give them grant/deny permissions, but how do I do this automatically so that every time a customer's details are added to a new row in the customer table, a new database user in the sidebar is added.
Try this
public static void AddUsersToDatabase(string databaseserver, string databasename, string usertobeadded)
{
using (SqlConnection conn = new SqlConnection("server=" + databaseserver + "; database=" + databasename + "; User ID=WPDOMAIN\\spdev; Integrated Security=SSPI; password=Password123;"))
{
conn.Open();
string password = "Password123";
string sql = "CREATE LOGIN " + usertobeadded + " WITH PASSWORD = '" +
password + "'; USE " + databasename + "; CREATE USER " + usertobeadded + " FOR LOGIN " + usertobeadded + ";";
SqlCommand cmd = new SqlCommand(sql);
cmd.ExecuteNonQuery();
conn.Close();
}
}

How to automate the process of restore db in SQL server?

In SQL server user have to follow below steps to restore database from backup file.
right click on the Databases container within object explorer.
from context menu select Restore database.
Specify To Database as either a new or existing database.
Specify Source for restore as from device.
Select Backup media as File.
Click the Add button and browse to the location of the BAK file.
Is there any script/command to restore the same without doing the above methods?
Just before you click on the last OK button on SSMS Backup/Restore Wizard ... you can Click on the script drop down button and pick script to New Query Window (The script drop down is Next to the Help button and above the Source/Database Name) and it will generate the Exact command that SSMS will execute against the DB. So you can use that command from the Query window to do the same thing programatically in TSQL. Indeed you can even put that inside a Stored PRocedure if you want to execute the same command all the time like so:
CREATE PROCEDURE dbo.dbBackup AS
BEGIN
RESTORE DATABASE [MyDataBaseName] FROM DISK = N'C:\SQLData\MyDB.bak'
WITH FILE = 1, NOUNLOAD, STATS = 5
END
And to take it one more level you could assign that SP to a hotkey as explained over here : https://www.mssqltips.com/sqlservertip/1287/assign-shortcuts-to-commands-in-sql-server-management-studio/
To access the screen below, open a query window and select from the menu Tools -> Options and then under the Environment node select Keyboard --> Query Shortcuts this will allow you to assign a stored procedure to execute for the Hotkey combination that is best for you.
One thing to be care full about though is to make sure that this does not replace an existing DB because you could accidentally overwrite a good DB if the restore command includes that option
"Automate" is a very broad term in your question, but if C# is an option, you can use the SQLCommand Class to execute the Restore, as below
sqlCmd.CommandText = "RESTORE DATABASE [" + restoreDbName + "] FROM DISK =
N'" + backupFileName + "' WITH FILE = 1, MOVE '" + logicalNameMdf + "' TO '"
+ restorePathMdf + "', MOVE '" + logicalNameLdf + "' TO '" + restorePathLdf + "', "
+ " NOUNLOAD, REPLACE";
sqlCmd.ExecuteNonQuery();

Unable to attach with sqlcipher encrypted database to another one

I'm working on an app that is using a database that is encrypted by sqlcipher. The passwort for this encryption is stored by cacheword.
To make a backup of my database I used the following code:
// ggf. Datenbank öffnen
openGuard();
mDb.execSQL("ATTACH DATABASE '" + outFileName + "' AS backup KEY 'asdfghjkl';");
mDb.rawExecSQL("SELECT sqlcipher_export('backup');");
mDb.execSQL("DETACH DATABASE backup;");
The method openGuard() is used to check if the database is opend yet and if not do this.
I've checked the backup by using an empty key to make an unencrypted copy of my database. Then I can use it on adb shell and use sql-statements to get the wanted data.
My problem now for a long time is that I'm not able to use my backup to restore the database of my app. I tried this code:
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(backupFile, "asdfghjkl", null);
db.execSQL("ATTACH DATABASE '" + dbFile + "' AS encrypted KEY '" + mCacheWord.getEncryptionKey() + "';");
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
Alternatively I tried
db.execSQL("ATTACH DATABASE '" + dbFile + "' AS encrypted KEY '" + encodeRawKey(mCacheWord.getEncryptionKey()) + "';");
But in both cases I get the following error message:
10-30 00:56:42.845: I/Database(14407): sqlite returned: error code = 26, msg = statement aborts at 5: [ATTACH DATABASE '/data/data/.../databases/database.db' AS encrypted KEY '[B#42082da0';] file is encrypted or is not a database
10-30 00:56:42.845: E/Database(14407): Failure 26 (file is encrypted or is not a database) on 0x63bdedb0 when executing 'ATTACH DATABASE '/data/data/.../databases/database.db' AS encrypted KEY '[B#42082da0';'
Is there anyone how can help me with my problem?
Looks like you've gotten accidentally "hung up" trying to decrypt by supplying the key via the ATTACH DATABASE statement. Looking at Example 2: Decrypt a SQLCipher database to a Plaintext Database of the API, there's a comment that reads -- empty key will disable encryption. So, presumably your initial decryption code attempt should first execute the PRAGMA key = statement (to supply the key) and then the ATTACH DATABASE statement with empty key (to decrypt) something like this:
db.execSQL("PRAGMA key = '" + mCacheWord.getEncryptionKey() + "';");
db.execSQL("ATTACH DATABASE '" + dbFile + "' AS encrypted KEY '';");
db.rawExecSQL("SELECT sqlcipher_export('encrypted')");
db.rawExecSQL("DETACH DATABASE encrypted;");
Another brief example about this can be seen in this the SQLCipher Users mailing list discussion.
I believe the problem may have to do with the fact that you are using CacheWord, which manages the encryption key separately from SQLCipher. You should verify the format of the string returned from getEncryptionKey() and ensure that it matches the proper format for a raw key in SQLCIpher.

Execute SQL Task Email

I am getting issue sending email from "Execute SQL Task"
failed with the following error:
"Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.
Here is SQL Statement-
USE msdb
GO
EXEC
sp_send_dbmail
#profile_name='DBAAdminSF',
#recipients='Aslone#yahoo.com',
#subject='Data uploaded',
#body=?
Parameter Mapping:
Variable Name User::Email_DB
Parameter Name =#body
It works fine when I include text for #body parameter directly in the query instead of using Parameter Mapping.
Help appreciated.
Have you tried overriding the script with Expressions instead of parameter mapping?
Sample Expression override i used for a recent project:
"Exec msdb.dbo.sp_send_dbmail
#profile_name='Email Profile',
#recipients='email_addy',
#copy_recipients='email_addy',
#subject=N'Subject Text" + #[User::FileMonth] + "',
#body=N'Body Text" + #[User::FileMonth] + "' ,
#file_attachments=N'" + #[User::FilePath] + "' "

Call to stored procedure fails in classic asp when the stored proc INSERTs or UPDATEs tables

I am developing/maintaining classic asp pages and asp code on a Windows 7 PC with data taking from an Sqlserver/Express 2008/R2.
In this code I use a stored procedure to log-on to the web site.
If the login-id and password combination is correct some tables are updated using UPDATE or INSERT.
If the login-id or password is not correct, no logging is issued( so no tables are updated ).
A result set is returned with some fields on both cases (with a field set to -1 or the internal user nr depending on the correctness of login-id and password).
I have been using this same routine for over 5 years now , running on all sorts of IIS servers and with all sorts of Sqlservers.
The code, which works on other IIS/Sqlservers combinations does not work on my development PC.
Any idea why?
Since it is a development environment I use the sqlserver SA account with the appropriate password. So as far as I can tell, this SA user should have all appropriate rights.
To be complete I will now give the routine ( but you will see it's very straight forward ):
function DoLogon( byval psNickName, byval psPassword)
dim sSql
DoLogon = False
psNickName = Trim(psNickName)
psPassword = Trim(psPassword)
if (psNickName = "") then exit function
if (psPassword = "") then exit function
' on error Resume Next
call DbOpen
sSql = "exec sp_EcomLogon " & SqlString( psNickName ) & "," & _
SqlString(psPassWord) & "," & _
SqlString(Request.ServerVariables("REMOTE_ADDR")) & "," & _
Trim(cStr(Session.SessionId))
objRec.Open sSql ,objConn ' ,adOpenStatic,adLockReadOnly ,adCmdText
Klant_NetId = FldDft("K_NetId",-1)
Call SetVarValue(cKlant_NetId,Klant_NetId)
objRec.Close
call DbClose
if Klant_NetId <> -1 then
DoLogon = True
Klant_IsLoggedOn = 1
else
DoLogon = False
Klant_IsLoggedOn = 0
end if
call SetVarValue(cKlant_IsLoggedOn, Klant_IsLoggedOn)
end function
The following error is displayed when the objRec.Close line is present:
ADODB.Recordset error '800a0e78'
Operation is not allowed when the object is closed.
Replacing the exec sp_... with a select * from ... works. So I presume the code it self is correct.
DbOpen and DbClose will allocate objRec and objConn and connect to / disconnect from the server (here SqlServer).
UPDATE AND SOLUTION
I have asked the person providing me with this solution to create an answer so I can give him proper upvotes, but in the mean time I will present the solution here.
As the first statement if the stored procedure I have added
set nocount on
And this seems to be the trick to get it working.
I have not found why this is necessary (from a technically view point), just that including set nocount on will speed up the stored procedures, but at last I have running stored procedures in combination with classic ASP again !
Try to add set nocount on to the top of the stored procedure?
It could be that the stored procedure that you are accessing is executing with an error. I would suggest that you write out the string sSql to screen copy it and execute it in query analyser to troubleshoot it.
I ran into a similar problem and in my case the issue was permissions on the table I was selecting from. I didn't have select permissions and it would close the connection. Now you mentioned that you are using the sa account so this should have permissions to all the functionality, but I would double check to make sure that this is true. HTH
Wade

Resources