Relative path for SQL not saving changes to database - c#

I am trying to add an SQL database to my project. I have been successful when using an explicit path, but if I use a relative path |DataDirectory|\Data\Database.mdf the console appears to be be writing data to the database, but looking in the server explorer at the database afterwards shows not data. There are a couple of other questions that get close to answering, but scouring Stack, I have been unable to locate an answer that works or comes close to addressing.
EDIT
Per the suggestions below I have attempted the fixes, however, just to clarify. The program appears to connect and write to the database as expected, but when I look at the database structure, no table is created, no data is inserted, even though the program runs with no errors
<connectionStrings>
<add name="rData"providerName="System.Data.SqlClient"connectionString="Data Source=(LocalDB)\MSSQLLocalDB; Initial Catalog=TestRecipeDatabase;AttachDbFilename=|DataDirectory|\Data\TestRecipeDatabase.mdf;Integrated Security=True" />
</connectionStrings>
public void connectToDB(string action)
{
var connectionString = ConfigurationManager.ConnectionStrings["rData"].ConnectionString;
Console.WriteLine(connectionString);
SqlConnection conn = new SqlConnection(connectionString);
if (action == "firstRun")
{
conn.Open();
// Creates the Database
try
{
using (SqlCommand createDBTable = new SqlCommand("" +
"CREATE TABLE RecipeStorage" +
"(" +
"rname char(50) NOT NULL, " +
"ringredients text, " +
"rdirections text" +
");", conn))
createDBTable.ExecuteNonQuery();
Console.WriteLine("Created Database");
}
catch (SqlException e)
{
Console.WriteLine(e.Message);
System.Diagnostics.Trace.WriteLine(logTime + " " + e.Message);
}
// Sets the primary key to rname
try
{
using (SqlCommand setPrimaryKey = new SqlCommand("ALTER TABLE RecipeStorage ADD PRIMARY KEY (rname);", conn))
setPrimaryKey.ExecuteNonQuery();
Console.WriteLine("Set Primary Key to Recipe Name");
}
catch (SqlException e)
{
Console.WriteLine(e.Message);
System.Diagnostics.Trace.WriteLine(logTime + " " +e.Message);
}
// Adds an initial recipe
try
{
using (SqlCommand firstLine = new SqlCommand("INSERT INTO RecipeStorage (rname, ringredients, rdirections) VALUES ('espresso', 'Hot water, coffee'," +
"'put coffee through espresso machine with hot water into cup, enjoy');", conn))
firstLine.ExecuteNonQuery();
}
catch (SqlException e)
{
Console.WriteLine(e.Message);
System.Diagnostics.Trace.WriteLine(logTime + " " + e.Message);
}
conn.Close();
}
}
As mentioned above, this totally works when using an explicit path for the data connection C:\User\User\Projects\CSharp\RecipeHandler\Data\TestRecipeDatabase.mdf
But does not work using the relative path. Ideally I would want to be able for this to run on any computer which obviously would not have the database in same place

Related

How to restore SQL Server backups using asp.net and C#?

How to restore SQL Server backup using C#?
try
{
string test = "D:\\backupdb\\05012017_130700.Bak";
sqlcmd = new SqlCommand("Restore database EmpolyeeTable from disk='D:\\backupdb\\05012017_130700.Bak'", con);
sqlcmd.ExecuteNonQuery();
Response.Write("restore database successfully");
}
catch (Exception ex)
{
Response.Write("Error During backup database!");
}
Quite weird requerement you have right there. I´ve never heard of someone restoring a database backup from a webpage, and as #Alex K. told, it would be quite rare that the user that uses your web application have the required previleges.
Anyway, supposing that everything told above is OK, the code to restore a backup would be this:
Use this:
using System.Data;
using System.Data.SqlClient;
Code:
private void TakeBackup()
{
var conn = new SqlConnection("Data Source=" + Server + ";Initial Catalog=" + Database + ";User Id=" + Username + ";Password=" + Password + ";");
try
{
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "RESTORE DATABASE AdventureWorks FROM DISK = 'C:\AdventureWorks.BAK' WITH REPLACE GO";
command.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
conn.Dispose();
conn.Close();
}
}
This is going to work specifically for the problem you posted. Be sure to set all the parameters of your database server on the connection string, it seems from the comments on your question that you are having communication issues. You have to solve that problems before you do anything. Some tips for that:
Be sure you set all the parameters on connection string the right way
Try to connect using another tool like ODBC so you can test all parameters
Check out SQL Network settings to see if TCP/IP is enabled

I'm trying to backup and restore database from SQL Server 2008

I'm trying to backup and restore a SQL Server 2008 database, but I'm getting an error saying
Incorrect Syntax near database name
Here is the code for back up and restore which is written c# asp.net.
Can I get a help regarding this?
private void btnbackup_Click(object sender, EventArgs e)
{
try
{
if (combodatabase.Text.CompareTo("") == 0)
{
MessageBox.Show("Please select a Database");
return;
}
con = new SqlConnection(connectionstring);
con.Open();
sql = "BACKUP DATABASE" + combodatabase.Text + " TO DISK='" + txtbackupfileloc.Text + "\\" + combodatabase.Text + "-" + DateTime.Now.Ticks.ToString() + ".bak'";
cmd = new SqlCommand(sql, con);
cmd.ExecuteNonQuery();
con.Close();
con.Dispose();
MessageBox.Show("Database Backup Successfully Completed.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Restore code:
private void btnrestore_Click(object sender, EventArgs e)
{
try
{
if (combodatabase.Text.CompareTo("") == 0)
{
MessageBox.Show("Please Select a Database");
return;
}
con = new SqlConnection(connectionstring);
con.Open();
sql = "ALTER DATABASE" + combodatabase.Text + "SET SINGLE_USR WITH ROLLBACK IMMEDIATELY ";
sql += "RESTORE DATABASE" + combodatabase.Text + "From DISK='" + txtrestorefileloc.Text + "'With REPLACE;";
cmd = new SqlCommand(sql, con);
cmd.ExecuteNonQuery();
con.Close();
con.Dispose();
MessageBox.Show("Database Successfully Restored");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
You don't have any whitespace between BACKUP DATABASE and the database name, that will be the first problem, the same goes for the second (restore) code.
You could attach yourself in debug mode to see what is the SQL command after you have built all your sql query string. It seems a lot of whitespaces are missing there. Once you have it, you could post it in SQL Server Management Studio and see tips for errors there, would be easier probably.
Last, but not least, if you can't debug your application easily or pop up the SQL query (which apparently isn't the case since you display the ex.Message), you could maybe run a SQL Server Profiler session to check the queries executed against SQL Server.
You're missing a few spaces in your SQL statements!
Check this out:
sql = "BACKUP DATABASE" + combodatabase.Text + " TO DISK='" + ....
If you select a database called TEST, this becomes:
BACKUP DATABASETEST TO DISK=.....
Or this:
sql = "ALTER DATABASE" + combodatabase.Text + "SET SINGLE_USR WITH ROLLBACK IMMEDIATELY ";
sql += "RESTORE DATABASE" + combodatabase.Text + "From DISK='" + txtrestorefileloc.Text + "'With REPLACE;";
becomes
ALTER DATABASETESTSET SINGLE_USR WITH ROLLBACK IMMEDIATELY
RESTORE DATABASETESTFrom DISK=......
There needs to be at least one space between the BACKUP DATABASE and the name of the database! Some throughout your code - you need to be more careful when stringing together keywords and placeholder - you need spaces between them at times!
Also, if your database name is "special" in any way (e.g. it contains a space itself, starts with a number etc.), you might need to put the database name into square brackets:
BACKUP DATABASE [Test DB] .....
BACKUP DATABASE [7dwarfs] .....

1GB of Data From MySQL to MS Access

The Situation: I am creating an automated task which queries MySQL (through ODBC) and inserts the result set to a MS Access Database (.mdb) using OLEDB.
The Code:
OleDbConnection accCon = new OleDbConnection();
OdbcCommand mySQLCon = new OdbcCommand();
try
{
//connect to mysql
Connect();
mySQLCon.Connection = connection;
//connect to access
accCon.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;" +
#"Data source= " + pathToAccess;
accCon.Open();
var cnt = 0;
while (cnt < 5)
{
if (accCon.State == ConnectionState.Open)
break;
cnt++;
System.Threading.Thread.Sleep(50);
}
if (cnt == 5)
{
ToolBox.logThis("Connection to Access DB did not open. Exit Process");
return;
}
} catch (Exception e)
{
ToolBox.logThis("Faild to Open connections. msg -> " + e.Message + "\\n" + e.StackTrace);
}
OleDbCommand accCmn = new OleDbCommand();
accCmn.Connection = accCon;
//access insert query structure
var insertAccessQuery = "INSERT INTO {0} values({1});";
// key = > tbl name in access, value = > mysql query to b executed
foreach (var table in tblNQuery)
{
try
{
mySQLCon.CommandText = table.Value;
//executed mysql query
using (var dataReader = mySQLCon.ExecuteReader())
{
//variable to hold row data
var rowData = new object[dataReader.FieldCount];
var parameters = "";
//read the result set from mysql query
while (dataReader.Read())
{
//fill rowData with the row values
dataReader.GetValues(rowData);
//build the parameters for insert query
for (var i = 0; i < dataReader.FieldCount; i++)
parameters += "'" + rowData[i] + "',";
parameters = parameters.TrimEnd(',');
//insert to access
accCmn.CommandText = string.Format(insertAccessQuery, table.Key, parameters);
try
{
accCmn.ExecuteNonQuery();
}
catch (Exception exc)
{
ToolBox.logThis("Faild to insert to access db. msg -> " + exc.Message + "\\n\\tInsert query -> " + accCmn.CommandText );
}
parameters = "";
}
}
}
catch (Exception e)
{
ToolBox.logThis("Faild to populate access db. msg -> " + e.Message + "\\n" + e.StackTrace);
}
}
Disconnect();
accCmn.Dispose();
accCon.Close();
The Issues:
The memory usage goes very high (300MB++) while the MS Access file size does not change constantly! Seems like the insert caches the data rather that saving it to disk.
It is very slow! I know my query executes within a few second but rather insertion process takes long.
I have tried using prepared statement in MS Access and insert the values as parameters instead of string concat to create insert query. However I get this exception message:
Data type mismatch in criteria expression.
Anyone know how to fix this or have a better approach?
You could create a VBA macro that uses the DoCmd.TransferDatabase method to pull data through ODBC into your Access database. It would probably be much faster and simpler as well.
To run the VBA code from an external program or scheduled task, simply initiate Access to open your file with the /x command line switch and it will run the import macro on startup. A GB of data though is still going to take a while. I found an article by David Catriel that implemented this approach.
An even better option is to use a different database engine back-end like the free version of SQL Server Express. Then you have a lot more options and it is much more robust. If you need MS Access forms and reports, you can create an ADP project file if you use SQL Server, or you can use linked tables to get at your data. You could even use Access as a front-end to your MySQL database instead of copying all the data if that would satisfy your requirements.
Instead of writing code, you could turn to SQL Server Integration Services (SSIS), and be done before lunch. It is available as an extension to Visual Studio, in case you do not have it on your computer already with SQL Server.
With SSIS you are able to create a reusable SSIS package that can be triggered from the command line or scheduled task. This guide shows how to pull data from MySQL into SQL Server, but the SQL Server part should be easy to replace with Access.
some changes with comment to add transaction for command execution. if transactions is not controlled manually, it will be created and committed every time automatically and it's a time consuming action
OleDbConnection accCon = new OleDbConnection();
OdbcCommand mySQLCon = new OdbcCommand();
try
{
//connect to mysql
Connect();
mySQLCon.Connection = connection;
//connect to access
accCon.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;" +
#"Data source= " + pathToAccess;
accCon.Open();
var cnt = 0;
while (cnt < 5)
{
if (accCon.State == ConnectionState.Open)
break;
cnt++;
System.Threading.Thread.Sleep(50);
}
if (cnt == 5)
{
ToolBox.logThis("Connection to Access DB did not open. Exit Process");
return;
}
}
catch (Exception e)
{
ToolBox.logThis("Faild to Open connections. msg -> " + e.Message + "\\n" + e.StackTrace);
}
//AMK: transaction starts here
var transaction = accCon.BeginTransaction();
OleDbCommand accCmn = new OleDbCommand();
accCmn.Connection = accCon;
accCmn.Transaction = transaction;
//access insert query structure
var insertAccessQuery = "INSERT INTO {0} values({1});";
// key = > tbl name in access, value = > mysql query to b executed
foreach (var table in tblNQuery)
{
try
{
mySQLCon.CommandText = table.Value;
//executed mysql query
using (var dataReader = mySQLCon.ExecuteReader())
{
//variable to hold row data
var rowData = new object[dataReader.FieldCount];
var parameters = "";
//read the result set from mysql query
while (dataReader.Read())
{
//fill rowData with the row values
dataReader.GetValues(rowData);
//build the parameters for insert query
for (var i = 0; i < dataReader.FieldCount; i++)
parameters += "'" + rowData[i] + "',";
parameters = parameters.TrimEnd(',');
//insert to access
accCmn.CommandText = string.Format(insertAccessQuery, table.Key, parameters);
try
{
accCmn.ExecuteNonQuery();
}
catch (Exception exc)
{
ToolBox.logThis("Faild to insert to access db. msg -> " + exc.Message +
"\\n\\tInsert query -> " + accCmn.CommandText);
}
parameters = "";
}
}
//AMK: transaction commits here if every thing is going well
transaction.Commit();
}
catch (Exception e)
{
ToolBox.logThis("Faild to populate access db. msg -> " + e.Message + "\\n" + e.StackTrace);
//AMK: transaction rollback here if there is a problem
transaction.Rollback();
}
}
Disconnect();
accCmn.Dispose();
accCon.Close();
Create a DSN (data source name) for the SQL server database. Then select that DSN by opening the Microsoft Access database and choosing to import from that DSN. You should have the ability to import that exact 1GB table (schema, data, everything).
More information on using a DSN:
https://support.office.com/en-us/article/Link-to-SQL-Server-data-0474c16d-a473-4458-9cf7-f369b78d3db8
Alternatively you can just link to the SQL server database (not import to an Access table) using that DSN and skip the import altogether.
Should the INSERT be part of a TRANSACTION. Being within a TRANSACTION usually speeds BULK INSERTS
Thanks everyone for the answers. I just found the main problem in my code. The reason for heavy memory usage (issue #1) was ODBC was caching the data from MySQL regardless of C# approach (DataReader). That issue is resolved by checking the Don't cache results of forward-only cursors checkbox in DSN settings. This also made the process slightly faster (30%). However, more concrete approach is still what Brian Pressler and Egil Hansen suggested.But since they require software installation and/or migration plan, easiest way would be to stick to this piece of code.

BackUp and Restore Sql Database By Admin User in Asp.Net, C#

Here, I have show my c# code for BackUp and Restore with Sql Database
In that back up is working properly but when i try to restore the database from backup folder, that time one error is occurred, and the error is:
RESTORE cannot process database 'UsersDB' because it is in use
by this session. It is recommended that the master database be used
when performing this operation. RESTORE DATABASE is terminating
abnormally.
BackUp button:
protected void btnbackup_Click(object sender, EventArgs e)
{
sqlcon.ConnectionString = (System.Configuration.ConfigurationManager.ConnectionStrings["conn"].ToString());
string destdir = "C:\\backupdb";
if (!System.IO.Directory.Exists(destdir))
{
System.IO.Directory.CreateDirectory("C:\\backupdb");
}
try
{
sqlcon.Open();
sqlcmd = new SqlCommand("backup database UsersDB to disk='" + destdir + "\\" + DateTime.Now.ToString("ddMMyyyy_HHmmss") + ".Bak'", sqlcon);
sqlcmd.ExecuteNonQuery();
Response.Write("Backup database successfully");
}
catch (Exception ex)
{
Response.Write("Error During backup database!");
}
}
Restore Button:
protected void btnrestore_Click(object sender, EventArgs e)
{
try
{
sqlcon.ConnectionString = (System.Configuration.ConfigurationManager.ConnectionStrings["conn"].ToString());
sqlcon.Open();
string destdir = "C:\\backupdb\\11082014_121403.Bak";
sqlcmd = new SqlCommand("Restore database UsersDB from disk='C:11082014_143650.Bak' ", sqlcon);
sqlcmd.ExecuteNonQuery();
Response.Write("restore database successfully");
}
catch (Exception ex)
{
Response.Write("Error During backup database!");
}
}
Thanks in advance
The error message itself saying that you can't connect to the exact database that you connected to.
You need to change your connection string so that instead of,
initial catalog=test_db
use this,
initial_catalog=master.
In the connection string you have connected to the database you want to backup.
Instead, connect to a different database or no database at all and it will work.

ExecuteNonQuery() not saving any record

I'm working a WinForms based C# tool which has an attached MDF file based database. I'm trying to use the SqlCommand.ExecuteNonQuery() method to save a record to this attached MDF database, but the record is not saved. No error or exception occurs; only problem is that the record is not actually saved.
I have a Console.WriteLine at the top which shows the query I'm trying to run. Its correct syntax-wise, and if I copy-paste it from the output windows and run it separately, it works.
I have correctly defined the connection string as the following, and it works fine for fetching records:
public static String connectionString = #"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\TestBuildDB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
Here the function I'm using to save records:
public static void PerformDBWriteTransaction(string inputSQLStatement)
{
Console.WriteLine(inputSQLStatement);
DataTable returnDataTable = new DataTable();
SqlConnection sqlConnection = new SqlConnection();
sqlConnection.ConnectionString = connectionString;
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlConnection;
cmd.CommandType = CommandType.Text;
cmd.CommandText = inputSQLStatement;
cmd.Connection.Open();
try
{
cmd.ExecuteNonQuery();
}
catch (SqlException ex)
{
errorMessages.Clear();
errorMessages.Append("The following errors were found in the SQL statement:\n\n");
for (int i = 0; i < ex.Errors.Count; i++)
{
errorMessages.Append("Index #" + i + "\n" +
"Message: " + ex.Errors[i].Message + "\n" +
"LineNumber: " + ex.Errors[i].LineNumber + "\n" +
"Source: " + ex.Errors[i].Source + "\n" +
"Procedure: " + ex.Errors[i].Procedure + "\n");
}
MessageBox.Show(errorMessages.ToString());
}
finally
{
cmd.Connection.Close();
}
}
Can someone tell me what might be the problem ? Do I need to perform a 'commit' somehow ?
EDIT:
I have found the problem, and have written up a solution below .. Thanks to all who helped me out though :)
I found the problem ! It was very simple, and it was stupid really :) .. The code above is all correct .. Yes, people pointed out optimizations, etc, but still the code above was correct.
The problem was that when I imported the TestDB.MDF file into my Visual 2010 project, a copy of that was made inside the project's folder. When you run/debug the program, another copy of the this file is made and is put in the \bin\Debug\ folder. In the connection string I was using, I had mentioned: AttachDbFilename=|DataDirectory|\TestBuildDB.mdf .. This meant that all reads/writes were done to the copy in the bin\Debug folder. However, the TestDB.MDF file I was looking into to verify if records were inserted or not, was in the project's folder ! So basically, there were two MDF files, and I was writing the records into one file, but was trying to find them in the other :)
When you add an MDF file into your VS2010 Project, VS2010 by default makes a connection to that MDF file, from where you can browse the stuff in that MDF file .. The MDF file used for this purpose was the one placed in the project's folder, NOT the one in bin\Debug\ folder. And like I said earlier, my code used the one in the bin\Debug folder :)
So what I've done now is that I've removed the Test.MDF file reference from my project, which removes the copy present in the project's folder. However, I DO have a copy of TestDB.MDF file in the bin\Debug\ folder, which I connect to from within my application. And if I want to browse the MDf file outside my project, I use SQL Management Studio. The only problem here is that an MDF file can only be used by one program at a given time. So if I have to use it with my application, I have to take it offline from SQL Management studio, and vica versa !
I hope this explanation helps someone out there :)
The solution to this problem is very simple just give the full path of the original MDF file in the connection String like this:
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=**C:\VISUAL STUDIO 2012\PROJECTS\ENGLISHTOHINDIDICTIONARY\ENGLISHTOHINDIDICTIONARY\DICTIONARY.MDF**;Initial Catalog=Dictionary;Integrated Security=false"
providerName="System.Data.SqlClient"
That's it, your problem is solved.
I had the same challenge, I simply changed the database property "Copy to Output Directory" from "Copy always" to "Do not copy" then moved my database.mdf (drag & drop from my IDE) into the bin\debug folder.
Tip:
The bin directory is normally hidden, use the "Show All Files" to display it
Provide a catch clause for all Exceptions. If there something wrong other than SqlException, you will never see what is it and your db will neved be updated. Imagine there is a FormatException...
Also check the return of ExecuteNonQuery : it's the number of rows affected by the query.
First, you should always wrap up your IDisposable objects in a using to ensure they're closed and disposed of properly (and that connection pooling can do its thing). Second, when modifying data wrap up your sql in a transaction to maintain data integrity.
Try the following code and see if any exceptions are raised. I wouldn't normally recommend catching Exception as it's too general, I'd let that bubble up to the calling mechanism and handle it there - but for this instance it will show you any and all issues. I think your particular issue is at the .Open stage of the connection, so try stepping through.
public static void PerformDBWriteTransaction(string inputSQLStatement)
{
DataTable returnDataTable = new DataTable();
try
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
using (SqlTransaction sqlTrans = sqlConnection.BeginTransaction())
{
try
{
using (SqlCommand cmd = new SqlCommand(inputSQLStatement, sqlConnection))
{
cmd.CommandType = CommandType.Text;
cmd.Transaction = sqlTrans;
cmd.ExecuteNonQuery();
}
}
catch (SqlException sqlEx)
{
sqlTrans.Rollback();
throw sqlEx;
}
sqlTrans.Commit();
}
}
}
catch (Exception ex)
{
errorMessages.Clear();
errorMessages.Append("The following errors were found in the SQL statement:\n\n");
for (int i = 0; i < ex.Errors.Count; i++)
{
errorMessages.Append("Index #" + i + "\n" +
"Message: " + ex.Errors[i].Message + "\n" +
"LineNumber: " + ex.Errors[i].LineNumber + "\n" +
"Source: " + ex.Errors[i].Source + "\n" +
"Procedure: " + ex.Errors[i].Procedure + "\n");
}
MessageBox.Show(errorMessages.ToString());
}
}
Hi I am working on library database when I add student record executionNonQuery
shows error like invalid column name page opens but saving data from not happening.
Here I have given the code statement
public partial class add_student_info : Form
{
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-SPT6GLG\SQLEXPRESS;Initial Catalog=library_managment;Integrated Security=True;Pooling=False");
public add_student_info()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "insert into student_info values('" + textBox1.Text + "','" + textBox2.Text + "','" + textBox3.Text + "','" + textBox4.Text + "'," + textBox5.Text + "," + textBox6.Text + "," + textBox7.Text + ")";
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Student recorc addedd sussfully");
}
}
}

Categories

Resources