If I restore from Sql Server no problem, but if I do it through my application, the database is stuck in "restoring state".
I found some advice saying to put noRecovery = false, but this didn't change anything.
If I remove the "with move" option, it works: after the restore the DB is in a normal state.
The thing that I would like to understand is: does "with move" modify a sql server table?
Because if I launch the restore the first time without "with move" it says that he could not find the specified path. Otherwise, if I launch the restore with this option, and then one second time without it, it works. So there must be some tables that sql server uses to map the logical name with a physical path, how can I modify this table?
Here is the code:
SqlConnection sqlConnection = new SqlConnection(string.Format("Data Source={0};Initial Catalog={1};Integrated Security=True", database.SqlServerId, database.Name));
ServerConnection connection = new ServerConnection(sqlConnection);
Server sqlServer = new Server(connection);
Restore rstDatabase = new Restore();
rstDatabase.Action = RestoreActionType.Database;
rstDatabase.Database = backupFile.Name;
BackupDeviceItem bkpDevice = new BackupDeviceItem(backupFile.FileName, DeviceType.File);
rstDatabase.Devices.Add(bkpDevice);
rstDatabase.ReplaceDatabase = true;
rstDatabase.NoRecovery = false;
string dbLogicalName = "";
string logLogicalName = "";
sqlConnection.Open();
SqlCommand command = new SqlCommand(string.Format("RESTORE FILELISTONLY FROM DISK = '{0}'", backupFile.FileName), sqlConnection);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
if (reader.GetString(2) == "D")
dbLogicalName = reader.GetString(0);
if (reader.GetString(2) == "L")
logLogicalName = reader.GetString(0);
}
}
reader.Close();
rstDatabase.RelocateFiles.Add(new RelocateFile(dbLogicalName, backupFile.DatabaseFile));
rstDatabase.RelocateFiles.Add(new RelocateFile(logLogicalName, backupFile.LogsFile));
//Restore
rstDatabase.SqlRestore(sqlServer);
rstDatabase.Devices.Remove(bkpDevice);
sqlConnection.Close();
connection.Disconnect();
The thing that I would like to understand is: does "with move" modify a sql server table?
Not necessarily, unless you modify the default databases path in the instance, which you could do in SSMS following these steps:
https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/view-or-change-the-default-locations-for-data-and-log-files
But as someone said, try to fix that on your own application. Do not attempt to modify this on the system database. It could bring unexpected results if you do that.
I think you know that, but WITH MOVE tells the SQL Server to reallocate the restored database in different path than the default path.
Related
I have for-each loop container in my SSIS master package
There is 'Execute Package Task'
under this 'Execute SQL Server Agent Job Task' is there.(It has 35 steps)
Problem:
SSIS master package is starting next iteration without completion of all the steps in 'Execute SQL Server Agent Job Task'.
Please suggest an approach to start the next iteration after completion of all the steps only.
Thanks in advance :)
I know I keep throwing C# solutions at SSIS problems but this is exactly what I do to prevent a job/process to run while a job is running.
I have a function that does this check and returns a boolean true/false. Use that result to determine whether to start the job or not.
public static bool isDatabaseUpdating()
{
List<string> jobs = new List<string>();
jobs.Add("[Insert name of Job here]");
jobs.Add("[Insert another job and so on here]");
string sql = "exec msdb.dbo.sp_help_job #execution_status = 1";
using (OleDbConnection conn = new OleDbConnection(cstr))
{
using (OleDbCommand cmd = new OleDbCommand(sql, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Connection.Open();
OleDbDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
if (jobs.Contains(rdr["name"].ToString())) return true;
}
}
}
return false;
}
To use it set a SSIS Variable like this:
Dts.Variables["#variableName"].Value = isDatabaseUpdating();
And then in control flow set expression on path appropriately.
The real key to understanding this function is the SQL.
exec msdb.dbo.sp_help_job #execution_status = 1
That returns a dataset of jobs that are currently running.
Enhancement to your application
This is what your control flow will look like:
I have the following code and Insert-statement.. and connection.
SqlConnection con = new SqlConnection();
con.ConnectionString = ("Data Source=DESKTOP-PGHMM6M;Initial Catalog=LocalUsers;Integrated Security=True");
con.Open();
string st = "INSERT INTO data(Username, Password, Hash, EncryptedPassword) VALUES (#Username, #Password, #Hash, #EncryptedPassword)";
SqlCommand cmd = new SqlCommand(st, con);
cmd.Parameters.AddWithValue("#Username", Username);
cmd.Parameters.AddWithValue("#Password", textBox2.Text);
cmd.Parameters.AddWithValue("#Hash", savedPasswordHash);
cmd.Parameters.AddWithValue("#EncryptedPassword", FinalEncryptedPass);
cmd.ExecuteNonQuery(); // invalid object name 'data' < where is this object?
con.Close();
When I run the program it returns the following error:
Invalid object name 'data'
I'm not sure what I did to create this situation. I was fulling around with the "stand-alone sql features" in Visual studio 2017, and I'm not sure where to start, to get back on track to use a local SQL Management Server Studio db that I created.
I found a previous question with the following::
Right click the database project --> Properties
Click Debug
Under Target Connection String, click Edit and select the correct database server
Create a new stored procedure
But I'm not sure what any of this is referring to ^.. any pointers?
welcome to stackoverflow.com
it says you do not have a table (in which you are inserting data) name : "data"...
you must have a database name "LocalUsers". in this database,
create a table name : "data" (with given fields) and you are good to go.
Currently I am using the SQLAdapter Update command to update changes from a DataTable to a SQL database. I want to know how to cache the changes for later if the server is not available. Is there a way to extract the SQL from the Update command and execute them later on the database?
sqlConn = New SqlConnection(AppConnection)
sqlConn.Open()
sqlAdapter = New SqlDataAdapter
sqlAdapter.SelectCommand = New SqlCommand
sqlAdapter.SelectCommand.Connection = sqlConn
sqlAdapter.SelectCommand.CommandText = "SELECT * FROM SampleTable"
Dim objSQLBuilder As SqlCommandBuilder = New SqlCommandBuilder(sqlAdapter)
'THIS IS NOT RETURNING THE COMPLETE SQL STATEMENT
sqlAdapter.UpdateCommand = objSQLBuilder.GetUpdateCommand()
'IF THIS FAILS, I WANT TO CACHE THE SQL AND EXECUTE THE SQL LATER...
sqlAdapter.Update(dtDataTable)
Thank you for any help!
I tried a few solutions and below is the most straight forward one but I get the error below
Logical file 'RestoredProcessMananger' is not part of database 'RestoredProcessMananger'. Use RESTORE FILELISTONLY to list the logical file names.
RESTORE DATABASE is terminating abnormally.
What am I doing wrong ? The idea is to create DLL to be used by other programs the allow a baseline database to be reloaded on a server overwriting whatever is there..
ServerConnection connection = new ServerConnection("xxx", "sa", "srv$xxx");
Server svr =new Server(connection);
Restore res = new Restore();
res.Database = "RestoredProcessMananger";
res.Action = RestoreActionType.Database;
res.Devices.AddDevice(#"C:\temp\ProcessManager.bak", DeviceType.File);
res.ReplaceDatabase = true;
res.RelocateFiles.Add(new RelocateFile("RestoredProcessMananger", _
#"c:\ProcessManager2.mdf"));
res.RelocateFiles.Add(new RelocateFile("RestoredProcessMananger_Log", _
#"c:\ProcessManager2_log.ldf"));
res.SqlRestore(svr);
svr.Refresh();
EDIT 1: fixed
public static void RestoreDatabase(string Server, //sqlserver //from CONFIG
string BackupFilePath, //where the bak file I want to restore //from CONFIG
string destinationDatabaseName, //what the restored database will be called //from CONFIG
string DatabaseFolder, //where the data/log files for the destination (break into 2 variables (2 different locations)) (get from GetDatabaseMDFFilePathName)
string DatabaseFileName, //the destination MDF file name (get from GetDatabaseMDFFilePathName)
string DatabaseLogFileName) //the destination LDF file name (get from GetDatabaseMDFFilePathName)
{
Server myServer = GetDatabases("xxx");
Restore myRestore = new Restore();
myRestore.Database = destinationDatabaseName;
Database currentDb = myServer.Databases[destinationDatabaseName];
if (currentDb != null)
myServer.KillAllProcesses(destinationDatabaseName);
myRestore.Devices.AddDevice(BackupFilePath, DeviceType.File);
string DataFileLocation = DatabaseFolder + "\\" + destinationDatabaseName + ".mdf";
string LogFileLocation = DatabaseFolder + "\\" + destinationDatabaseName + "_log.ldf";
myRestore.RelocateFiles.Add(new RelocateFile(DatabaseFileName, DataFileLocation));
myRestore.RelocateFiles.Add(new RelocateFile(DatabaseLogFileName, LogFileLocation));
myRestore.ReplaceDatabase = true;
myRestore.PercentCompleteNotification = 10;
myRestore.SqlRestore(myServer);
currentDb = myServer.Databases[destinationDatabaseName];
currentDb.SetOnline();
}
The error indicates that RestoredProcessMananger is not the name of a logical file contained in your backup file.
Have you used RESTORE FILELISTONLY ... to list the files contained in the .BAK file?
For instance, if your backup file is named C:\MyBackupFile.bak you would need to run the following query from SQL Server Management Studio (or SQLCMD, etc):
RESTORE FILELISTONLY FROM DISK='C:\MyBackupFile.bak';
This will provide a list of the logical files contained in the backup file. You will then need to pass the name of one of these files into your RelocateFile code.
I am using following code to attach my database to SQL Server. The problem is if I create a new file and attach it through my code but when I detach the file using SSMS and again run the same code, it gives error.
Error is:
Unable to open the physical file "e:\dbForATTWithPWD.mdf". Operating
system error 2: "2(error not found)"
The code is:
Dim conn As New SqlConnection("Server=MyHomeServer\SQLExpress;Database=master;Integrated Security=SSPI")
Dim cmd As New SqlCommand("", conn)
cmd.CommandText = "CREATE DATABASE MyHomeWithPWD ON ( FILENAME = 'e:\dbForATTWithPWD.mdf' ), ( FILENAME = 'e:\dbForATTWithPWD_log.ldf' ) FOR ATTACH"
conn.Open()
cmd.ExecuteNonQuery()
cmd.Dispose()
conn.Dispose()
Why is it happening. All the permissions are the same even first time.
Also what should be the connection string if I need to use DB with uid sa and pwd abc123 ?
Thanks
Try to making sure that nothing else is accessing that mdb file after you detach it. I would probably shutdown that SQLServer instance and restart. Also, I'd make sure that you could detach and reattach in SSMS.
For your connection string try this: "Server=YOURSVR;Database=DB;Trusted_Connection=False;User ID=sa;Password=abc123;"