How to copy mdf file into a folder with c# - c#

I'm using c# and I have a small SQL Server database that I need to copy into a folder C:\databases\, the method name is CreateCopy.
But at File.Copy row appear an error:
"The Process cannot Access the File, because it is being use by another Process"
I read that File.Copy can be execute only after shut SqlServer down or Detach that database, create a copy and turn SqlServer on again. But how to do it by code?
This is the method that I was trying to use:
public static void CreateCopy()
{
try
{
DateTime date = DateTime.Now;
SqlConnection connection = new SqlConnection(MDF_CONNECTION_STRING);
String dbpath = String.Format(#"C:\databases\{0:yyyyMMdd}.mdf", Cash, date);
File.Copy(#"C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\database.mdf", dbpath);
String lgpath = String.Format(#"C:\databases\{0:yyyyMMdd}_log.ldf", Cash, date);
File.Copy(#"C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\database_log.ldf", lgpath);
}
catch(Exception e)
{
throw new ApplicationException("Error", e);
}
}
Thanks in advance!
INFO
This is not a duplicate of here because i don't need to do create a bak file, i need to archive this database. I need just to copy these two files (.mdf and .ldf) into a folder. And that answers didn't help me

What I understand is that you are looking for the code which will help you to Programmatically Enumerating, Attaching, and Detaching SQL Server Databases So that you can copy the MDF file to the location. You can also have a look on How to Backup and Restore to get the idea of AttachDbFilename mode.

Database files .mdf and .ldf files are used by the SQL Server engine.
If you DETACH database from SQL Server instance, then you can copy or move those files.
But when you DETACH db, it will be unaccessible!
So it is better to run a backup command in SQL then use it.

Remove SqlConnection connection = new SqlConnection(MDF_CONNECTION_STRING); it will access the .mdf file and give it after the File.Copy() execute. because at the time of execution of File.Copy() the file is being used by SqlConnection that's because you are getting such error

Related

Restore SQL Server database on a remote server using C#

I need to write a C# program that restores a SQL Server database at a remote computer and I need to do this from local computer. My code is restoring database but I need to put path to backup .bak file at remote computer using "From Disk".
string sql = "ALTER DATABASE [" + MyDatabaseName + "] ; Restore Database [" + MyDatabaseName + "] From Disk= '" + pathToBackupAtRemoteComputer + "'WITH REPLACE;"
When I delete database using SQL Server Management Studio and run code, I get an error that database does not exist or I don't have permission. I want to 1st: delete database, 2nd: create new database, 3rd: put data from backup file. Is there an option to write something like: "DROP SCHEMA IF NOT EXITS" or "CREATE DATABASE IF NOT EXIST" (like in MySQL)? I tried but it didn't work.
Is there an option that I can use .bak file at my local computer (like in MySQL, when I transfer .sql file at local computer into string then restore database remotely)? Or maybe send .bak file from local to remote computer using C# application and do it automatically? I tried it out using PsExec, but there is no option to transfer file between two computers.
One way to delete database is by using the following:
USE master;
ALTER DATABASE [MyDatabaseName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [MyDatabaseName] ;
This way, it will drop the database and the physical files .ldf and .mdf files. Another thing is you can also rename the database (and maybe compare the database with restored one)
A good article on renaming a database logical and physical files are here:
https://www.mssqltips.com/sqlservertip/1891/steps-to-rename-a-sql-server-database/
DROP DATABASE IF EXISTS is possible in SQL Server in SQL Server 2016 onwards.
Because it is the SQL Server database engine performing the restore, the backup file must be accessible to the remote SQL Server and could be a UNC path.

Can't access mdf file in desktop application

I need your help.. maybe it's the small task which I am not able to solve but I don't know how to search that on any search engine
I am using an .mdf file (vs 2103) in my WPF login register desktop application.. Everything is working fine, no compilation errors. I inserted some data into the .mdf file by using query in Visual Studio and then try to login through application and it's working fine. Moreover I am also able to register, i.e., insert into .mdf file from the register option of application if I use the "absolute path" of the .mdf file. Problem begins when I try to insert into .mdf file using a "relative path"... it doesn't insert data into the .mdf....I don't know why.
(this absolute path is not working. I have .mdf file in the database folder)
//connection string
connetionString = #"Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Database\Database1.mdf;Integrated Security=True";
//code
SqlCommand sqlCmd;
string sql = null;
SqlConnection sqlCnn = new SqlConnection(connetionString);
try
{
sqlCnn.Open();
sql = "insert into [NewTable] ( Name , Password ) values ('ABC' , '12345')";
sqlCmd = new SqlCommand(sql, sqlCnn);
sqlCmd.ExecuteNonQuery();
sqlCnn.Close();
MessageBox.Show("You have Been Registered");
}
catch (Exception ex)
{
MessageBox.Show("" + ex);
}
It shows the message "You have Been Registered"
but is not visible in .mdf file...
I want to ask..why is it behaving like this....and I want to use the relative path as we cant judge the client system absolute path...what mistake I am doing? how to handle this (i guess self made) issue?
The whole AttachDbFileName= approach is flawed - at best! When running your app in Visual Studio, it will be copying around the .mdf file (from your App_Data directory to the output directory - typically .\bin\debug - where you app runs) and most likely, your INSERT works just fine - but you're just looking at the wrong .mdf file in the end!
If you want to stick with this approach, then try putting a breakpoint on the myConnection.Close() call - and then inspect the .mdf file with SQL Server Mgmt Studio Express - I'm almost certain your data is there.
The real solution in my opinion would be to
install SQL Server Express (and you've already done that anyway)
install SQL Server Management Studio Express
create your database in SSMS Express, give it a logical name (e.g. MyDatabase)
connect to it using its logical database name (given when you create it on the server) - and don't mess around with physical database files and user instances. In that case, your connection string would be something like:
Data Source=.\\SQLEXPRESS;Database=MyDatabase;Integrated Security=True
and everything else is exactly the same as before...
Also see Aaron Bertrand excellent blog article Bad habits to kick: Using AttachDbFileName for more in depth explanations and tips

How To Get Sql Database Backup File's Data and Log File Paths Using SMO in C#

I have found several posts about how to perform a database backup and database restore using the Sql SMO assemblies in C#. Basically if I want to make a copy of a database and give it a new name, I need to provide Relocate Files when doing the Restore. The Relocate Files consist of a Data File path and Log File path. If I'm restoring from an existing database then I can simply inspect the Database object's FileGroups property to get the Data File path, and it's LogFiles property to get the Log File path, then modify the path's filename to use the new database name, and provide these when doing the Restore. Without providing the Relocate Files the Restore operation would just overwrite the original database (overwrite it's .mdf (data) and .ldf (log) files).
So I have all that working fine, but now I've run into the case where I want to create a new database from a database backup file (.bak) that the user supplies, and they should be able to specify a new name for the database. In order to give the database a new name and not overwrite the existing database files (if they exist already), I need to know the backup file's Data and Log File paths.
Are there SMO functions that I can use to inspect a database backup file for it's database name, Data File path, and Log File path? I'm assuming there are, since SQL Management Studio is able to do it, but looking through the MSDN documentation I haven't come across it yet.
Thanks in advance.
== ANSWER ==
As linked to in Ben Thul's answer, the answer is to use the ReadFileList function on the Restore object. Here is some sample code:
Restore restore = new Restore();
restore.Devices.AddDevice(Path.GetFullPath(backupFileToRestoreFrom), DeviceType.File);
DataTable fileList = restore.ReadFileList(server);
string dataLogicalName = fileList.Rows[0][0].ToString();
string dataPhysicalName = fileList.Rows[0][1].ToString();
string logLogicalName = fileList.Rows[1][0].ToString();
string logPhysicalName = fileList.Rows[1][1].ToString();
Check this out: how to restore using restore class of Microsoft.SqlServer.Management.Smo namespace. In T-SQL, you'd accomplish this with restore filelistonly from disk='path_to_your_backup'

Using Smo.Backup to backup SQL Server database to string

I'm trying to make a little app that would help me making my server backup. That app would run on my home PC so the main goal is to be able to connect to the external server, backup the selected database, dump the backup content to a string or something so I could write it on my PC disk and not the server's disk.
I did that which works to write on the server's disk, but I'd like to be able to write on my PC's disk the backup's result.
private bool BackupDatabase()
{
try
{
// Filename
string sFileName = string.Format("{0}\\{1}.bak", _sWhereToBackup, DatabaseName);
// Connection
string sConnectionString = String.Format(
"Data Source=tcp:{0};Initial Catalog={1};User ID={2};Pwd={3};",
DatabaseHost, DatabaseName, DatabaseUsername, DatabasePassword);
SqlConnection oSqlConnection = new SqlConnection(sConnectionString);
Server oServer = new Server(new ServerConnection(oSqlConnection));
// Backup
Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = DatabaseName;
backup.Incremental = false;
backup.Initialize = true;
backup.LogTruncation = BackupTruncateLogType.Truncate;
// Backup Device
BackupDeviceItem backupItemDevice = new BackupDeviceItem(sFileName, DeviceType.File);
backup.Devices.Add(backupItemDevice);
// Start Backup
backup.SqlBackup(oServer);
}
catch (Exception ex)
{
throw ex;
}
return false;
}
Thanks so much!
This is going to get a bit hacky because you need to either
call sql functions to read the file on the server and return as a binary array to you and then convert back to a file. this will require proper permissions as the account you are running under to access the file on the server's drive.
you can use t-sql or a bit more 'advanced' .net code
t-sql can be seen in this great sql injection guide
http://www.blackhat.com/presentations/bh-europe-09/Guimaraes/Blackhat-europe-09-Damele-SQLInjection-slides.pdf
or .net:
http://www.mssqltips.com/sqlservertip/2349/read-and-write-binary-files-with-the-sql-server-clr/
map a file location (i.e. access a share/drive/ipc connection) over the network
have the server ftp the files to a location
Which sounds likely in your scenario?
I take it that you're not networked to the server? Ideally you could back it up directly to your machine using a network address but I'm guessing you would have already thought of that.
Going the route you're thinking of is going to require you to have permissions that you would not normally want to have opened up to the someone over the internet, and will be much more trouble to program than simply setting up a second process to move the file somewhere accessible to you.
Adams suggestion to have the server ftp the files is a good one. Alternatively, you may find that using DropBox (www.dropbox.com) might be the path of least resistance. Then you could just back the database up to a folder setup with dropbox and it will automatically be copied to any folder you setup on your machine to be synchronized with it.
You should look into DAC, it is mainly made for the SQL Server in Azure, but will work with a SQL Server 2008 R2 too.
http://sqldacexamples.codeplex.com/

Problem In Open Or Use master.mdf database in C#

I define Sql_Cmd And Other sql variable that need before
and Now write this code:
string strConnection2 = "Data Source=.\\sqlexpress;AttachDbFilename=master.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
SqlConnection sqlcon2 = new SqlConnection(strConnection2);
string sql = "select * ";
Sql_Cmd.CommandType = CommandType.Text;
Sql_Cmd.CommandText = sql;
Sql_Cmd.Connection = sqlcon2;
try
{
sqlcon2.Open();
Sql_Cmd.ExecuteNonQuery();
}
catch (SqlException Error_Exception)
{
//FormError1 = new FormErrorInDataBase();
//FormError1.Show();
}
When I want to open sqlcon2 I see this error:
An attempt to attach an auto-named database for file master.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
Please help me - how can I open master database and then use select query for this database, and what is the connection string for master.mdf?
Can I write the directory of mater.mdf such as C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\master.mdf or is it enough that I write AttachDbFilename=master.mdf?
Are you trying to open 'the' master database? The system database called 'master' is used internally by SQL Server and should not / does not need to be opened or attached in this way. If not, you'll have to call your database something other than 'master' - that is a reserved database name.
Check your parameters again. The right syntax to add an .mdf-file is as follows. Attach a database file on connect to a local SQL Server Express instance:
Server=.\SQLExpress;AttachDbFilename=c:\asd\qwe\mydbfile.mdf;Database=dbname; Trusted_Connection=Yes;
Why is the Database parameter needed? If the named database have already been attached, SQL Server does not reattach it. It uses the attached database as the default for the connection.
See: connectionstrings.com
master database is the system database that contains system information about SQL Server instance, information about databases contained in this instance and so on. This database is opened automatically when SQL Server starts.
So, when you want to connect to SQL Server, master database is already exist and cannot be attached. Information about this database you can see here
I cannot understand why you need to attach this database. Maybe you don't need to attach this database, but only connect to it? If so, you need to change th code:
string strConnection2 = "Data Source=.\\sqlexpress;initial catalog=master;Integrated Security=True;Connect Timeout=30;"

Categories

Resources