Programmatically detach SQL Server database to copy mdf file - c#

I have a small SQL Server database that I need to copy on command -- I need to be able to take the mfd and ldf files at any given moment, copy them, zip them, and make them available to an end user.
Right now this is possible by manually:
1) Logging onto the SQL server via Remote Desktop
2) Detaching the database via SQL Management Studio. I have to fiddle around with a combination of setting the database to single_user and/or restarting the service so I can get it to detach since the app server is normally logged into it.
3) While detached I go through the file system and copy the mdf and ldf files.
4) I re-attach the database via SQL Management Studio
5) I zip the copied files, and I move them to an FTP server so the people who need them can get them.
It's a horrible, inefficient process. It's not just a matter of needing the schema, but rather a need for people to work with snapshots of real, production data on their own local machines for the purpose of destructive experimentation. Luckily the zipped database is very small -- maybe 30 megs with the log.
So ideally, I'd like to create a page in the ASP .NET web application that has a button the user can press to initiate the packaging of the current database into a zip file, and then I'd just provide the link to the file download.

Why not make a ordinary backup (easy to do with sqlcommand) and add a feature for the users to easy restore that backupfile with a click on a button?
You can backup the database with sql-commands
You can shell out and zip the backupfile with sql-commands
You can also shell out and ftp the backupfile automagically to an webserver if you want.
What are the end users using to consume your db? A winform-program? Then it easy done to do everything with a button click for the user.
Here are some example code for that:
Declare #CustomerID int
declare #FileName nvarchar(40)
declare #ZipFileName nvarchar(40)
declare #ZipComand nvarchar(255)
set #CustomerID=20 --Get from database instead in real life application
SET #FileName='c:\backups\myback'+ cast(#customerID as nvarchar(10))+'.bak'
SET #ZipFileName='c:\backups\myback'+ cast(#customerID as nvarchar(10))+'.zip'
--Backup database northwind
backup database northwind to DISK=#FileName
--Zip the file, I got a commanddriven zip.exe from the net somewhere.
set #ZipComand= 'zip.exe -r '+#ZipFileName+' '+#FileName
EXEC xp_cmdshell #zipcomand,NO_output
--Execute the batfile that ftp:s the file to the server
exec xp_cmdshell 'c:\movetoftp.bat',no_output
--Done!
You have to have a movetoftp.bat that contains this (change ftp-server to your):
ftp -s:ftpcommands.txt ftp.myftp.net
And you have to have a ftpcommands.txt that contains this (You can have this file created dnamically with just the right zip-file by sqlcommands too, but I let you do that yourself):
ftpusername
ftppassword
binary
prompt n
mput c:\backups\*.zip
quit

Look at the dialogues you use in SQL Management Studio, near the top of each is a button which will generate a scrip to perform the action. This is a quick way to discover how to do this in SQL which can be executed from a database connection.
E.g. to detach database db1:
EXEC master.dbo.sp_detach_db #dbname = N'db1'

Easy - check into the "SQL management objects" SMO that come with SQL Server - nice C# / VB.NET classes and methods to do all of this.
See: SMO - manage your SQL Server!
or:
SQL Server 2005 Database Backup and Restore using C# and .NET 2.0
Marc

Personally I'd generate backups of the database and zip those and send them to the users. Perhaps you could write a small script to restore.
Reason being detaching the database makes it unavailable for others.

I'd use SQL Dumper console version and compress the sql dump.
IMHO it's always better to have a plain text copy instead of a binary file. If something goes wrong, at least you can rewrite your data by hand, because you can read it.

First Connect to SQL Server With no Attach any DB File and with no use Database name.
ConnectionString = #"Data Source=XXX;Integrated Security=True;Connect Timeout=30";
Note: XXX = . OR .\SQLEXPRESS OR .\MSSQLSERVER OR (local)\SQLEXPRESS OR (localdb)\v11.0 &...
then by under Query Detach your DB file.
"ALTER DATABASE [your DB] SET OFFLINE WITH ROLLBACK IMMEDIATE \n\r exec sp_detach_db #dbname = [your DB]";
Ok.
My Sample code:
sql_connect1.ConnectionString = #"Data Source=.\sqlexpress;Integrated Security=True;Connect Timeout=30";
sql_command.CommandText = "ALTER DATABASE [IRAN] SET OFFLINE WITH ROLLBACK IMMEDIATE \n\r exec sp_detach_db #dbname = [IRAN]";
sql_command.Connection = sql_connect1;
sql_connect1.Open();
sql_command.ExecuteNonQuery();
sql_connect1.Close();

Related

bcp holding the csv file forever and not writing anything from the table back to the CSV when called from c#.net website

"DBNAME" represents - server name
The following is sql statement 
set #sql = 'bcp xxxxx.dbo.CsvTemp out D:/EDI/INCOMING/test1.csv  -c -t, -T -SDBNAME'
which is part of a stored procedure "SP1".
When i call this "SP1" from .net website. BCP utility just creates the file at the location , does not write anything to it and holds the file forever.
when i run it from SQL management server. It works fine.
Really stuck.
don't know what to do.
Thanks
Shweta

How to connect to a SQL Server instance without knowing the Initial Catalog?

I'm writing a portable program that can be used on other computers as well as mine and It also connects to the SQL Database on that computer.
So the problem is that I don't have the database name of that computer. How can my program connect to that Database without previously knowing the database name?
In other words, I don't have enough information to create a complete ConnectionString.
Connect to SQL Server's master database first.
Then, using this query, you can get data from databases in your database:
SELECT name FROM master.dbo.sysdatabases
Using the site below, you can find the right Connection strings for you :
https://www.connectionstrings.com/
You can use a dot in the connection string to represent.tbe local server.
Create a txt file, rename the extension to UDL. Open the UDL file and put a dot, a full stop:
If you have installed a SQL Instance (ie not the default instance) it will be .\InstanceName
Choose the Database drop down and click Test Connect.
Finally close the URL file and open it with NotePad and you will see the connection string.

c# SQL) unable to open physical file(MS localdb .mdf) after attaching the .mdf file which was created in another computer(server)

I'm developing Windows Desktop appication(C# WPF) with Microsoft localdb(.mdf) and I want that users of my software can carry their localdb (.mdf) file when they move to other places(computers). The localdb (.mdf) file is created on the first computer.
To test my application, I copied my localdb file from computer A to computer B and attached with below code successfully.
string attach_greendbnameQuery = string.Format(#"EXEC sp_attach_db #dbname = N'greendb_{0}', #filename1 = N'{1}\greendb_{0}.mdf'", textBoxGreenLogin.Text, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToString());
SqlCommand attach_greendbnamecomm = new SqlCommand(attach_greendbnameQuery, check_datadbinmasterConn);
attach_greendbnamecomm.ExecuteNonQuery();
And I could read and write data into the moved localdb file.
However, when I run backup command on this database, exception occurs like,
'Unable to open physical file, Operating system error 32, process cannot open the file because the file is in use by another process'
If I enter Server Management Studio- Security-KayLee-PC\KayLee- User Mapping,
the users of all other localdb are 'dbo' but only the user of manually moved database is KayLee-PC\KayLee and only 'public' is checked and all other database roles are not checked including db_owner. (I always start(login) Windows(O/S) with KayLee-PC\Kaylee account)
I tried to make all roles checked to database roles even to server roles but failed.
Even, I tried to drop the user KayLee-PC\KayLee through below code but the exception message show as,
'User 'KayLee-PC\KayLee' does not exist in current database'
If I click the database in Server Management Studio, the current database status is not changed to clicked database and subtree nodes(like Table, Security and so on) are not displayed with message 'cannot access to the database' eventhough if I click other databases, the current database status is changed to clicked database.
Also, I tried to change the owner of the localdb(database) through below code but it seems the execution failed with result '-1' with 'sa' and when trying with 'KayLee-PC\KayLee' which I always login to Windows O/S, error message is like 'KayLee-PC\KayLee is already an owner(exist) of this database'
SqlConnection dbownerchange_Conn = new SqlConnection();
dbownerchange_Conn.ConnectionString = dbownerchange_ConnectionString;
dbownerchange_Conn.Open();
SqlCommand dbownerchange_comm = new SqlCommand();
dbownerchange_comm.Connection = dbownerchange_Conn;
dbownerchange_comm.CommandText = "EXEC sp_changedbowner 'sa'";
dbownerchange_comm.ExecuteNonQuery();
dbownerchange_Conn.Close();
Simply, If we need to move(copy) Microsoft localdb file to another place(computer), how can I do this successfully?
Must we detach before move the localdb file? If so, I'm worried there're always people who don't follow guideline by running detach function.
I've tried several scenarios to understand how SQL server is working. The conclusion is we need to detach first and re-attach to same or different machine(computer). Then, I could have been successful to move to another computer.
However, a single process of backup and restoring localdb to another machine(computer) doesn't work. Furthermore, if we detach localdb(database file .mdf) first, SQL server no more recognizes the localdb database and we cannot run backup command for the localdb.
Conclusively and simply, if we want to move localdb (microsoft database .mdf file) to other local server(computer, machine), we're needed to just detach the localdb from master database in computer A and copy the files and re-attach to another master database of computer B.
Hope this helps someone else..

Is there a universal connection string for different computers to connect to a local database using my program developed by vs2010

newbie here.
I have a local db in my program. Whilst I was developing the program I used the SQL
Connection string :
SqlConnection sconn = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\leemk_000\Documents\......Integrated Security=True;User Instance=True;");
Now If I want to load this program onto a different computer I am sure that this connection will no longer work simply because it will still be looking for Users\Lee_000\
I have tried to remove Lee_000 but I get this following error:
An attempt to attach an auto-named database for file C:\Users\Documents..... failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
What can I do to get a connection string to work on different computers.
With many thanks
The whole User Instance and AttachDbFileName= approach is flawed - at best - especially when you want to share your database amongst multiple clients!
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. YourDatabase)
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=YourDatabase;Integrated Security=True
and everything else is exactly the same as before...
If it's a local db you should be placing it within the app folder and carry it with the app right?
Put the database in the App_data folder of your app and use that in your connection string
<add name="YourConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\yourfile.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>
You need to use a database server and let your users use it via your connection string like this;
Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;
"myServerAddress" should be the ip adress of your server machine.

Creating MySql Database on new install of c# application if it doesnt exist

I am about to deploy my application and have came into a bit of trouble.
I have the connection string for the database held in the application.settings and need a way to check if the database exists when the program first starts up, and if it doesn't, i need the program to create it before starting the program.
I am assuming it would be a mysql statement to check if db exists, if not create. However, I don't know where or how to do this, can I create a mysql dump of a blank database with tables etc already created and use that?
I have already stored the mysql dll files locally so there is no problem with that, its just creating the database that the string wants to connect to before the application runs so there are no connection errors straight away.
Thanks.
You can do this by running the following SQL statement:
SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = "my_db"
If it doesn't exist from the result set you get returned you can then create it.
This does pose questions regarding MySQL permissions and if your application should have user rights that enable such checking.
Edit in response of comments.
It isn’t clear if you create the connection string or not – I’ll assume the worst and that it is a part of the setup so your client can enter it (if you do know it the process below simplifies.
I would pass the connection string to the constructor of the MySqlConnectionStringBuilder class, this then makes it easy to connect to the database using the MySqlConnection class. I would use the properties from the new instance of the MySqlConnectionStringBuilder class (Server, Host, User etc) to setup the MySqlConnection class.
If the connection didn’t work I would return information to the user and they can update their connection string.
Once I’ve successfully connected to the database I would then use the database name from the Database property of my MySqlConnectionStringBuilder instance to build the query above.
If the command returns NULL the database doesn't exist and then needs creating, if the database does exist then the command will return the name of the database.
Now there are two paths:
It Doesn't exist – It needs creating, I would probably have an external SQL file with the create statements in (can be produced by MySQL dump by using the –nodata option). I would parse this file and execute the create statements
It does exist – I would now check the structure of the database to make sure it is compatible before continuing the installation.

Categories