Can't restore database with LocalDB - sql-server

I have been using this code for about 2 years to restore 2008 r2 backup to 2008 r2 and it works every time. I am now trying to use the same code to restore from 2008 r2 backup to 2012 localdb and it fails every time. The error message is below. Not only does the restore fail, it leaves my current database in 'recovery pending' state, and is unusable. I am using c# and this must all be done programmatically with no user or DBA involvement. Can you help me get this thing back on track?
using(var connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = String.Format("Alter Database {0} SET SINGLE_USER With ROLLBACK IMMEDIATE", dbName);
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
connection.Open();
cmd.ExecuteNonQuery();
SqlCommand cmd2 = new SqlCommand();
cmd2.CommandText = String.Format(#"RESTORE DATABASE {0} FROM DISK = '{1}'", dbName, backupFilePath);
cmd2.CommandType = CommandType.Text;
cmd2.Connection = connection;
cmd2.ExecuteNonQuery();
}
System.Data.SqlClient.SqlException (0x80131904): The logical database file 'MyData_log' cannot be found. Specify the full path for the file.
RESTORE could not start database 'MyData'.
RESTORE DATABASE is terminating abnormally.
Edit: changed one line to
cmd2.CommandText = String.Format(#"RESTORE DATABASE {0} FROM DISK = '{1}' WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 5", dbName, backupFilePath);
So far has made no difference.

Shouldn't you RESTORE DATABASE and use the WITH REPLACE option? And does your connection string connect you to the 'master' database for running these commands, rather than the database being restored?
Have you used SQL Server Management Studio to look at the database file name and locations for the *.mdf and *.ldf files?
I also find that sometimes the very FIRST restore of a database doesn't work as expected, but subsequent ones do... have you tried manually restoring the database (using SQL Server Management Studio... right-click the DB, tasks, restore database), and then tried running the code programmatically?
Generally, when doing restores programmatically, you want to grab the file names of the mdf and ldf files, and then specify them in the RESTORE command with the "WITH REPLACE" option.

Related

VB.Net code to Backup and Save SQL Server database won't work

I'm using following code to back up a SQL Server database using VB.Net to some other physical location. But I get the following error when trying to save it inside clients PCs. In some clients, it works on external hard drives but not on all clients.
Cannot open backup device 'D:\11-16-2020_POS_DB_MM.bak'. Operating system error 5(Access is denied.)
BACKUP DATABASE is terminating abnormally.
I understand it's an error happening due to user permissions. Is it possible to rectify this in my code or do I always have to set user permissions in every client (database is in a server and there are multiple clients. I use a setup package to deploy on clients)
Public Class frmBackup
Private connString As String = "Data Source=SQLSERVER\SLMA;Database=master;User Id=sa;Password =" & dbPwd & ";"
Private con As SqlConnection = New SqlConnection(connString)
Private Sub cmbbackup_Click(sender As Object, e As EventArgs) Handles cmbbackup.Click
Try
SaveFileDialog1.FileName = DateAndTime.DateString + "_" + dbName
SaveFileDialog1.Filter = "SQL Server database backup files|*.bak"
SaveFileDialog1.ShowDialog()
Dim cmd As New SqlCommand("BACKUP DATABASE " & dbName & " To disk='" & SaveFileDialog1.FileName & "'", conn)
If Not conn.State = ConnectionState.Open Then
conn.Open()
End If
cmd.ExecuteNonQuery()
conn.Close()
MsgBox("The database was successfully backup to - " & System.IO.Path.GetFullPath(OpenFileDialog1.FileName))
Catch ex As Exception
MsgBox(Err.Description)
Me.Close()
End Try
End Sub
End Class
Database is in a server and there are multiple clients. I use a setup package to deploy on clients
BACKUP always runs on the server, and any drives would have to be mouted on the server, not the client. You can't just plug in a thumbdrive on a client and backup a database on the server to it.
Also note that in Windows only administrators can write files to the root of a drive. If you do want to put the backup on the D: drive you should create a folder for it and grant permissions on that.
A database on a server should have an automated backup configured, but if you want to initiate an ad-hoc backup and you have no access to the server, you can backup the database to an Azure Blob Storage Account using Backup to URL.
Rather than sacrificing security by changing directory/file permissions, you can make your own subdirectory in the directory returned by Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), set the ACL for that subdirectory so that all users have read and write permission, create the backup in that subdirectory, then move the resulting file to the user's selected location. The file move will be done in the context of the user using your program.
You could also take the opportunity to make the backup into a password-protected zip archive.

Data upload from Visual Studio to SQL Server Timeout

I have a big Problem sending an SQL-Dump made with SQL-Server Management Studio via vb.net to another SQL-Server.
I made the SQL-Files like this: Database / Tasks / scripts ...
After deleting every "GO" command in the Dump I managed to upload to my local SQL-Server 2012. But this worked only if I made different scripts for any table.
If I use one big File, I get a timeout.
Now I want to transfer the Data (50 MB) to another SQL Server via Internet connection.
Only 3 of 5 Tables are generated on this server :-(
I get the following timeout error (german version, sorry):
"Eine Ausnahme (erste Chance) des Typs "System.Data.SqlClient.SqlException" ist in System.Data.dll aufgetreten.
Timeout abgelaufen. Das Zeitlimit wurde vor dem Beenden des Vorgangs überschritten oder der Server reagiert nicht."
Any Idea which side makes the timeout (SQL-Server oder vb.net)?
Is there a safer method uploading lots of data to a SQL-Server?
This is the code I use (The SQL-Skript is in My.Resources.SQLDump):
'####SQLDump #######
Dim SQLscript As String = My.Resources.SQLDump
SQLscript = "USE [" + TextBoxDB.Text + "] " + vbCrLf + SQLscript
Using connection As New SqlConnection(Verbind.ConStr)
Using command As New SqlCommand()
' Set the connection
command.Connection = connection
' Not necessary, but good practice
command.CommandType = CommandType.Text
' Example query using parameters
command.CommandText = SQLscript
Try
connection.Open()
rowsAffected = command.ExecuteNonQuery()
Catch ex As Exception
Debug.Print(ex.Message)
Finally
command.Dispose()
connection.Dispose()
End Try
'command.ExecuteNonQuery()
End Using ' Dispose Command
End Using ' Dispose (and hence Close) Connection
MsgBox("DB-Upload 1/5 fertig!")
Is there a safer method uploading lots of data to a SQL-Server?
Yes, there are couple of ways to load data into SQL Server
bcp Utility
BULK INSERT statement
OPENROWSET
SQL Server Import and Export Wizard
Important note: On a 64-bit computer, Integration Services installs
the 64-bit version of the SQL Server Import and Export Wizard
(DTSWizard.exe). However, some data sources, such as Access or Excel,
only have a 32-bit provider available. To work with these data
sources, you might have to install and run the 32-bit version of the
wizard. To install the 32-bit version of the wizard, select either
Client Tools or SQL Server Data Tools (SSDT) during setup.
SSIS
Tutorial to create a SSIS package
Being a SSIS developer I can go in deep and demostrate possible ways to import data by using SSIS like
Bulk import
Script task
Flat file source/ Excel source
Etc Etc.. but that would be different from the question which you have asked.
Regarding, resolving your error you can set the command timeout property in your code to make it run for any specific time limit or limitless.
command.CommandTimeout = 1;
Note: The CommandTimeout property will be ignored during asynchronous
method calls such as BeginExecuteReader.
Edited
Here is the sample code
Using command As New SqlCommand()
command.Connection = connection
command.CommandType = CommandType.Text
command.CommandText = SQLscript
command.CommandTimeout = 1
Try
connection.Open()
rowsAffected = command.ExecuteNonQuery()
Catch ex As Exception
Debug.Print(ex.Message)
Finally
command.Dispose()
connection.Dispose()
End Try
End Using
Other way is to extend connection timeout in your connection string. It accept integer which indicates seconds (in below example connection timeout is set to 30 seconds; 0 means unlimited)
Connection Timeout=30;
Import / Export Wizard for one time move
Since you were able to generate scripts, you have access to the source. Since you're able to execute them, you have access to the destination, and you have Management Studio installed. Your fastest option, IMO, is the Import Export utility provided by Sql Server.
In Sql Server Management Studio, right click on the source database name, click on "Tasks" and then click on "Export Data". This opens up a wizard that will let you put in Source, Destination, and pick the objects you want to export.
While 50 MB of scripts is large, 50MB of data move should finish within a matter of minutes.
Moving data over and over again
You have several options, I would go with OpenRowset, especially for the size of data you're moving. Here's a reference https://msdn.microsoft.com/en-us/library/ms190312.aspx
If you go into moving Gigabytes worth of data regularly, then SSIS packages are your best option. Here's a tutorial https://msdn.microsoft.com/en-us/library/ms169917.aspx

Script to replicate SQL Server data dynamicaly

I have an access 2010 application with a SQL Server database.
But I need to do an offline version. So I thought I would create a local SQL Server database on their computers then they can run a script to update their data before they go on the road.
NOTE: There won't be any sync. The data in offline mode is only for read-only and any changes will be lost.
I tried with Management Studio like this:
But I realized that the data is hard coded instead of doing inserts from selects.
Is there any easy way to create the script?
What I have so far is my pass through query in access to create the backup of my online database.
Then I have my pass through query to restore the backup to the local server.
The only problem is how can I build the connection string for the second query. It's currently set to this one
ODBC;DRIVER=SQL Server;SERVER=010-068\SQLEXPRESS;UID=marcAndreL;Trusted_Connection=Yes;DATABASE=SMD
but because it's a different database for everyone, it won't work.
How can we build a custom connection string?
I am using SQL Server Express 2012 and Windows Authentication, so using the answer provided here, I find this works for me:
Sub TestCon()
Dim cn As New ADODB.Connection
cn.Open ServerConLocal
End Sub
Function ServerConLocal()
''OleDB Connection
ServerConLocal = "Provider=sqloledb;Data Source=localhost\SQLEXPRESS;" _
& "Initial Catalog=Test;Integrated Security=SSPI;"
End Function
For an ODBC connection string in a Pass-through query, this works for me:
ODBC;Driver={SQL Server Native Client 11.0};Server=localhost\SQLEXPRESS;Database=test;
Trusted_Connection=yes;
Take a look at download-only articles for merge replication. MSDN.

don't see the new database and can't log in

I create a database using ADO.NET SQL queries like this:
create database mydatabase
create login 'loginname' with password='somepassword'
create user 'username' for login loginname
The queries aren't exact, I've typed them as far as I could remember them.
After that I don't see the database in my ms sql server 2008 r2 express management studio.
I also can't log in with the newly created login. The "enable server authentication" is set to true.
What should I do to see that database in the manager?
Why can't I log in with newly created login? I've looked into the logs and it says that the password is incorrect.
I do have 2 sql express instances, but I use the same one when I run my sql
select ##servername when run in management studio returns "BOGDAN".
ADO.NET query returns "BOGDAN\BBF17ECB-69FF-4B" . Code is below:
SqlConnection con = new SqlConnection("Data Source=BOGDAN;Integrated Security=True;User Instance=True");
SqlCommand cmd = new SqlCommand("select ##servername", con);
con.Open();
string s = (string)cmd.ExecuteScalar();
Console.WriteLine("Server name:" + s);
con.Close();
Console.ReadKey(false);
Don't know where BBF17ECB-69FF-4B came from, I explicitly stated server name as "BOGDAN".
the script is:
IF DB_ID('MyDatabase') IS NULL CREATE DATABASE [MyDatabase]
USE MyDatabase
IF NOT EXISTS(SELECT * FROM master.dbo.syslogins WHERE loginname = 'AUsername') CREATE LOGIN AUsername WITH PASSWORD='APassword'
IF NOT EXISTS (SELECT * FROM sys.sysusers WHERE name='AUsername') CREATE USER AUsername FOR LOGIN AUsername
EXEC sp_addrolemember N'db_owner', N'AUsername'
Do you have multiple instances of Sql Server on your box? Maybe an express install, and a developer edition install? It's possible you were pointed at the other instance when you created the db...I have done this before.
Are you sure that the database creation completed without error? Maybe it failed, and the db was never created.
Unfortunately, the details of the query that you would have run are where we would find the evidence for the problem.
The problem was with the connection string: I had to remove "User Instance=true" from it. That fixed the problem!
I thought the problem was with how I configurated the servers or with the SQL requests.

Duplicate SQL Server database on same server cannot be accessed

I am using SQL Server Workgroup Edition on Windows Server 2003 R2
My classic ASP pages access my production database using a system DSN. All working here.
Code like this...
<%
dbName= "ProdDB"
userID = "PublicUser"
pwd = "PublicUserPW"
Set objConn = Server.createObject("ADODB.Connection")
objConn.connectionString = "DSN=MySystemDSN"
objConn.open dbName, userID, pwd
%>
For development and testing, I created a copy of ProdDB in Enterprise Manager by
Backing up ProdDB
Restoring from the ProdDB backup set to a new database called TestDB
My understanding was that the restored database would contain an exact copy of the data as well as users, roles etc. Comparing both databases in Enterprise Manager seemed to back up this assumption.
So... I assumed I can access the test copy using the same credentials and only change the dbName, like so...
<%
dbName= "TestDB"
userID = "PublicUser"
pwd = "PublicUserPW"
Set objConn = Server.createObject("ADODB.Connection")
objConn.connectionString = "DSN=MySystemDSN"
objConn.open dbName, userID, pwd
%>
However, now my page returns
[Microsoft][ODBC Driver Manager] Data
source name not found and no default
driver specified
I have even tried creating a new System DSN, with a default database pointing at TestDB. Still no joy.
I'm sure I'm doing something simple and silly. Any assistance gratefully received.
The documentation for the open method says it's declared:
connection.Open ConnectionString, UserID, Password, Options
So it looks like you're passing in TestDB as the connection string. I usually call open without specifying any arguments. Grab a connection string from connectionstrings dot com, and:
objConn.ConnectionString = "Data Source=localhost;Initial Catalog=testdb;" & _
"User Id=myUsername;Password=myPassword;"
objConn.Open

Resources