Detach local database .mdf, copy, attach the new file - c#

I tried to detach my local database .mdf copy it in another folder and attach the new file at launch and copy to the older folder when closing.
It seems to works at launch but i have an error when the form closing :
The process cannot access the file 'C:\ProgramData\MyData\db1.mdf' because it is being used by another process.
That's my code :
public Form()
{
InitializeComponent();
DetachDatabase();
CopyDb();
AttachDatabase();
AppDomain.CurrentDomain.SetData("DataDirectory", Data.MyNewFolder);
}
public static bool DetachDatabase()
{
try
{
string connectionString = String.Format(#"Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True");
using (var cn = new SqlConnection(connectionString))
{
cn.Open();
SqlCommand cmd = cn.CreateCommand();
cmd.CommandText = String.Format("exec sp_detach_db '{0}'", "db1");
cmd.ExecuteNonQuery();
cmd.CommandText = String.Format("exec sp_detach_db '{0}'", "db2");
cmd.ExecuteNonQuery();
return true;
}
}
catch
{
return false;
}
}
public static bool AttachDatabase()
{
try
{
string connectionString = String.Format(#"Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True");
using (var cn = new SqlConnection(connectionString))
{
cn.Open();
SqlCommand cmd = cn.CreateCommand();
cmd.CommandText = String.Format("exec sys.sp_attach_db db1, 'db1.mdf'");
cmd.CommandText = String.Format("exec sys.sp_attach_db db2, 'db2.mdf'");
cmd.ExecuteNonQuery();
return true;
}
}
catch
{
return false;
}
}
private void Frm_FormClosing(object sender, FormClosingEventArgs e)
{
LocalDB.DetachDatabase();
CopyDb();
LocalDB.AttachDatabase();
}
what is the good way for do it ?
Thanks

You need to switch to master and put the target database offline
WARNING: Use at your own risk (e.g. can you use WITH ROLLBACK IMMEDIATE?)
var commandText = string.Format(#"
USE MASTER;
ALTER DATABASE {0} SET OFFLINE WITH ROLLBACK IMMEDIATE;
EXEC sp_detach_db '{0}', 'true';", "db1");
The second parameter to sp_detach_db just avoids statistics update (would be faster)
You can now safely move the mdf and ldf files from their original location
Assuming your database is already offline and you have moved your db1.mdf file into D:\Whatever, I think you can do this ( I didn't test it, beware )
var commandText = string.Format(#"
USE MASTER;
ALTER DATABASE {0}
MODIFY FILE (
NAME = '{0}',
FILENAME = 'D:\Wherever\{0}.mdf');
ALTER DATABASE {0} SET ONLINE;", "db1");

Related

TSQL logging inside transaction using CLR stored procedure

I'm trying to write a log into another database inside a transaction so that the log will survive even if the transaction is rolled back. I've read this answer which says:
One possibility is to use a CLR stored procedure to do the logging. This can open its own connection to the database outside the transaction and enter and commit the log data.
So I created CLR stored procedure using this article:
[SqlProcedure]
public static void Voice(SqlString procedureName, SqlInt32 id)
{
Connection = new SqlConnectionStringBuilder();
Connection.ContextConnection = true;
using (TransactionScope transScope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(Connection.ToString()))
{
conn.Open();
SqlCommand cmdInsert = conn.CreateCommand();
cmdInsert.CommandText = sql;
cmdInsert.Parameters.Add("#id", SqlDbType.Int);
cmdInsert.Parameters[0].Value = id;
cmdInsert.Parameters.Add("#procedureName", SqlDbType.NVarChar);
cmdInsert.Parameters[1].Value = procedureName;
cmdInsert.ExecuteNonQuery();
}
transScope.Complete();
}
}
However, data is not saved afer I executed and rolled back stored procedure in SQL Server:
BEGIN TRAN
EXEC dbo.SayHelloVoice #id = 1,
#procedureName = N'FooProcedure'
ROLLBACK TRAN
We have three environments:
dev. Server name is Q-SQL001
test. Server name is Q-SQL002
prod. Server name is Q-SQL003
So this CLR stored procedure should work on all environments.
Could you say what I am doing wrong?
Any help would be greatly appreciated!
UPDATE:
So the work version looks like this. Big thanks to the #Milney:
var serverName = string.Empty;
var dbName = string.Empty;
serverName = SqlExecuteScalar("SELECT ##SERVERNAME");
dbName = SqlExecuteScalar("SELECT DB_NAME()");
SqlConnectionStringBuilder sqlConn = new SqlConnectionStringBuilder();
sqlConn.InitialCatalog = dbName;
sqlConn.DataSource = serverName;
sqlConn.IntegratedSecurity = true;
sqlConn.ContextConnection = false;
sqlConn.Enlist = false;
sqlConn.ApplicationName = "New application";
var sql = "USE FooDatabase
INSERT INTO dbo.MyTable ..."
using (SqlConnection conn2 = new SqlConnection(sqlConn.ConnectionString))
{
conn2.Open();
SqlCommand cmdInsert = conn2.CreateCommand();
cmdInsert.CommandText = sql;
cmdInsert.Parameters.Add("#id", SqlDbType.Int);
cmdInsert.Parameters[0].Value = storeTime;
cmdInsert.Parameters.Add("#messageText", SqlDbType.NVarChar);
cmdInsert.Parameters[1].Value = messageText;
cmdInsert.ExecuteNonQuery();
}
If you use:
Connection.ContextConnection = true;
Then it's going to use the same connection that the CLR Sproc is running in - you need to open a new connection.

Generating SQL Database on Client PC

I have an application that uses SQL Server and I am working on a setup that should generate the Database on the Client machine from a script.
As a prerequisite for installation I have selected SQL Server Express 2012 and the .Net Framework.
My question is, will SQL Server Express 2012 be enough to make accessing the database possible on the Client machine?
Also, will my Code for generating the Database from the script run on another PC, specifically the "Data Source=.\BeneSQL" worries me, since that is "unique" to my PC, or will the script generate that part aswell?
private void Form1_Load(object sender, EventArgs e)
{
if (!CheckDatabaseExist())
{
GenerateDatabase();
}
}
private bool CheckDatabaseExist()
{
SqlConnection sqlConnection = new SqlConnection(#"Data Source=.\BeneSQL;Initial Catalog=TryingDB;Integrated Security=True");
try
{
sqlConnection.Open();
return true;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
return false;
}
}
private void GenerateDatabase()
{
List<string> cmds = new List<string>();
if (File.Exists(Application.StartupPath + "\\Skript.sql"))
{
TextReader tr = new StreamReader(Application.StartupPath + "\\Skript.sql");
string line = "";
string cmd = "";
while ((line = tr.ReadLine()) != null)
{
if (line.Trim().ToUpper() == "GO")
{
cmds.Add(cmd);
cmd = "";
}
else
{
cmd += line + "\r\n";
}
}
if (cmd.Length > 0)
{
cmds.Add(cmd);
cmd = "";
}
tr.Close();
}
if (cmds.Count > 0)
{
SqlCommand command = new SqlCommand();
command.Connection = new SqlConnection(#"Data Source=.\BeneSQL;Initial Catalog=MASTER;Integrated Security=True");
command.CommandType = System.Data.CommandType.Text;
command.Connection.Open();
for(int i=0; i<cmds.Count; i++)
{
command.CommandText = cmds[i];
command.ExecuteNonQuery();
}
}
}
It depends on what instance name will be used for the SQL Server 2012 installation.
If SQL Server is installed on a default instance (.) without name, your code will not work, because it will not be able to connect to the instance .\BeneSQL , because it will not exist.
Otherwise, if SQL Server is installed on an instance named BeneSQL , then your code should work, because it will find the instance.
I can't see that working for the reasons you suspect.
Try
command.Connection = new SqlConnection(#"Data Source=localhost;Initial Catalog=MASTER;Integrated Security=True");

Connection string for local database in C#

Maybe it's repetitive but I googled and didn't find my answer.
I developed a program by .net that has a local database (Express) that works excellently on my computer, but when I create a setup and installation, it can't insert or update and so on for example in Delete() method I have
try
{
}
catch
{
}
in the exefile always goes to the catch{} section and I don't know why :((
This is my connection string:
Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;Connect Timeout=30
This is one of my methods for example:
private Boolean Delete(int id)
{
//String conString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=C:\\Users\\Parnian\\documents\\visual studio 2017\\Projects\\Bank\\Bank\\Database.mdf;Integrated Security=True";
SqlConnection sql = new SqlConnection(Connection);
String sqll = "Delete FROM TblBank WHERE Id =#id ";
try
{
sql.Open();
SqlCommand cmd = new SqlCommand(sqll, sql);
cmd.Parameters.AddWithValue("id", id);
cmd.CommandType = System.Data.CommandType.Text;
cmd.ExecuteNonQuery();
sql.Close();
return true;
}
catch (Exception ex)
{
MessageBoxEx.Show("have some problem", "wrong", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
and Necessary say i put my .mdf and .ldf file into my setup folder and make setup by Visual Studio Installer
Try this
private bool Delete(int id)
{
string connString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=C:\\Users\\Parnian\\documents\\visual studio 2017\\Projects\\Bank\\Bank\\Database.mdf;Integrated Security=True";
SqlConnection sqlConn = new SqlConnection(connString);
String sql = "Delete FROM TblBank WHERE Id =#id ";
try
{
sqlConn.Open();
SqlCommand cmd = new SqlCommand(sql, sqlConn);
cmd.Parameters.AddWithValue("id", id);
cmd.CommandType = System.Data.CommandType.Text;
cmd.ExecuteNonQuery();
sql.Close();
return true;
}
catch (Exception ex)
{
MessageBoxEx.Show(ex.Message, "wrong", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
So that you can see what the error is. At the moment you are just saying something went wrong when ex contains everything you will need to debug the problem.
Hope this helps.
(There are a few things to refactor too, such as wrapping your connection in a using statement.)
The cause of your problem is very simple. There can be two situations in your case. They are as follows:
The computer you are trying to run the application doesn't have the proper version of the sql server.
Solution: In this case, you have to find out in which sql server version you have created your database. Then you have to include that version of sql server into the setup.exe package. So that when the setup.exe executes the proper sql server also setups with your application.
The computer you are trying to setup the application has proper sql version but still you are getting the error.
Solution: First delete your existing database and create new database from solution explorer.Then use this particular connection string given below
SqlConnection conn = new
SqlConnection (global::ProjectName.Properties.Settings.Default.ProjectConnectionString);
ProjectConnectionString can be found in App.config file after you connect your database to your solution.
Hope this helps. Feel free to ask in the comment if you need to.
#Parnian It should required to install local db in your system.
1.when you click server object explorer and then when you click on Localdb server you will get proper connection string from properties .
enter code here static void Main(string[] args)
{
TestConncetion testConncetion = new TestConncetion(Delete);//here I used delegate
WriteLine($"My connection string is working Fine ,result is {testConncetion(1)}");
}
private static bool Delete(int id)
{
string Connection = #"Data Source=(localdb)\ProjectsV13;Initial Catalog=master;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
//String conString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=C:\\Users\\Parnian\\documents\\visual studio 2017\\Projects\\Bank\\Bank\\Database.mdf;Integrated Security=True";
SqlConnection sql = new SqlConnection(Connection);
string sqll = "Delete FROM TblBank WHERE Id =#id ";
try
{
sql.Open();
SqlCommand cmd = new SqlCommand(sqll, sql);
cmd.Parameters.AddWithValue("id", id);
cmd.CommandType = System.Data.CommandType.Text;
cmd.ExecuteNonQuery();
sql.Close();
return true;
}
catch (Exception ex)
{
WriteLine("have some problem", "wrong", ex.Message);
return false;
}
}

C# Connection must be valid and open Mysql

is there something wrong with my codes. I already try another codes but the problem is still the same. I've been solving this error for a couple of weeks now, and i can't figure it out how to solve it. And also I already try some another code but the problem is still the same.
I want to save a multiple row from dataGrid to my database.
here's the codes that i use to save a multiple row
private void button1_Click(object sender, EventArgs e)
{
MySqlConnection conString = new MySqlConnection("datasource = localhost; port = 3306; Initial catalog = dbnewsystem; username = root;password = 1234");
MySqlCommand command1 = new MySqlCommand("INSERT INTO purchaseorder (orNo, ProdNo, Quantity, total)" +
"VALUES(#ORNo,#ProductNo,#quantity,#total )", conString);
command1.Parameters.AddWithValue("#ORNo", dataGridView1.Rows.Count);
command1.Parameters.AddWithValue("#ProductNo", dataGridView1.Rows.Count);
command1.Parameters.AddWithValue("#quantity", dataGridView1.Rows.Count);
command1.Parameters.AddWithValue("#total", textBox6.Text);
conString.Open();
command1.ExecuteNonQuery();
command1.Connection = conString;
conString.Close();
command1.CommandType = CommandType.StoredProcedure;
command1.CommandText = "pos_save";
if (command1.ExecuteNonQuery() == 1)
{
MessageBox.Show("saved");
}
else
{
MessageBox.Show("Sorry Nothing to be Update");
}
conString.Close();
}
change sequence
command1.Connection = conString;
command1.ExecuteNonQuery();
You have implemented wrong sequence:
...
conString.Open(); // Connection opened
command1.ExecuteNonQuery(); // Try executing (fail)
command1.Connection = conString; // Connection assigned
Change to
conString.Open(); // Connection opened
command1.Connection = conString; // Connection assigned
command1.ExecuteNonQuery(); // Try executing (fail)
A better design is
// Wrap IDisposable into using
using (MySqlConnection conString = new MySqlConnection("...")) {
conString.Open();
// Make SQL Readable
string sql =
#"INSERT INTO purchaseorder(
orNo,
ProdNo,
Quantity,
total)
VALUES(
#ORNo,
#ProductNo,
#quantity,
#total)";
// Wrap IDisposable into using
using (MySqlCommand command1 = new MySqlCommand(sql, conString)) {
command1.Parameters.AddWithValue("#ORNo", dataGridView1.Rows.Count);
command1.Parameters.AddWithValue("#ProductNo", dataGridView1.Rows.Count);
command1.Parameters.AddWithValue("#quantity", dataGridView1.Rows.Count);
command1.Parameters.AddWithValue("#total", textBox6.Text);
command1.ExecuteNonQuery();
}
}

SQL Server insert

I have a simple two-field form that stores its data in the database. For some reason, it isn't working. I have verified that the connection string works, as it is used in another project I made.
I didn't include the beginning of the first class or its page load.
Code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string Name = txtName.Text;
string Description = txtSpecial.Text;
string method = string.Format(
"INSERT INTO RbSpecials (Name,Description,Active) VALUES ('{0}','{1}','1')",
Name,
Description);
RbConfiguration mySql = new RbConfiguration();
try
{
mySql.Sql_Connection(method);
}
catch
{
}
}
}
public class RbConfiguration
{
string DbConnectionString = "System.Configuration.ConfigurationManager.ConnectionStrings['RBConnectionString'].ConnectionString";
public void Sql_Connection(string queryString)
{
SqlConnection conn = new SqlConnection(DbConnectionString);
SqlCommand cmd = new SqlCommand(queryString, conn);
conn.Open();
conn.Close();
}
}
You never execute your SQL command:
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
And your connection string is wrong (ditch the double quotes):
string DbConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RBConnectionString"].ConnectionString;
Well without knowing the error, I'll give it a shot anyway.
string DbConnectionString = "System.Configuration.ConfigurationManager.ConnectionStrings['RBConnectionString'].ConnectionString";
Should be
string DbConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RBConnectionString"].ConnectionString;
And as Adam says, you never actually execute your Query.
The Sql_Connection-method, only opens a connection, and then closes it again, without actually doing anything.
Try this instead:
public void Sql_Connection(string queryString)
{
using( SqlConnection conn = new SqlConnection(DbConnectionString) )
{
SqlCommand cmd = new SqlCommand(queryString, conn);
conn.Open();
cmd.ExecuteNonQuery();
}
}
Check your connection string code must not be a string its class which is getting connection string from web.config, so it should be like this
string DbConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["RBConnectionString"].ConnectionString;
You did not execute your SQlCommand, so will it insert the data, do this
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
its not the cause but the best practice to not to make your code vulnerable to SQLINjection, try this article
How To: Protect From SQL Injection in ASP.NET

Categories