Beginner's question - please can I ask for advice on creating local database files programmatically at run time. I want to be able later to rename, delete them etc using Windows Explorer in the same way as for text and other files, and to copy them to other computers.
This is using Visual Studio Community 15 with C#, installed SQL server Data Tools 14.0.50616.0. The computer has Microsoft SQL Server 2014.
For an example I have removed the surplus parts of my program to leave the code below, which uses a Windows Form Application with 3 buttons (btnCreateDb, btnDeleteDb, and btnDoesDbExist) and a combobox cbxDb for the database name. It makes databases in an existing folder C:\DbTemp.
It will apparently create and delete a new database and make files, for example mydb1.mdf and mydb1.ldf in the folder, and state that they exist. However, if I delete the two files using Explorer, it throws an exception if an attempt is made to delete or to create the database; and btnDoesDbExist shows that it still exists.
Why does the database still appear to exist when the files have been deleted by Windows Explorer? The code under btnDoesDatabaseExist doesn't refer to the path of the files, so it must be seeing something else, but where? Is this a correct method for the user of the program to create, delete, and detect these databases?
using System;
using System.Data;
using System.Windows.Forms;
//my additions
using System.Data.SqlClient;
namespace DataProg15
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static string form1ConnectionString = "Data Source = (LocalDB)\\MSSQLLocalDB; Integrated Security = True; Connect Timeout = 30; ";
private string form1DatabasePath = "C:\\DbTemp";
private void btnCreateDb_Click(object sender, EventArgs e)
{
string nameToCreate = cbxDb.Text;
SqlConnection myConn = new SqlConnection(form1ConnectionString);
string str = "CREATE DATABASE " +nameToCreate+ " ON PRIMARY " +
"(NAME = " +nameToCreate+ "_Data, " +
"FILENAME = '" +form1DatabasePath+ "\\" +nameToCreate+ ".mdf', " +
"SIZE = 4MB, MAXSIZE = 10MB, FILEGROWTH = 10%) " +
"LOG ON (NAME = " +nameToCreate+ "_Log, " +
"FILENAME = '" +form1DatabasePath+ "\\" +nameToCreate+ ".ldf', " +
"SIZE = 1MB, " +
"MAXSIZE = 5MB, " +
"FILEGROWTH = 10%)";
SqlCommand myCommand = new SqlCommand(str, myConn);
try
{
myConn.Open();
myCommand.ExecuteNonQuery();
MessageBox.Show("DataBase '" + nameToCreate + "' was created successfully");
}
catch (System.Exception ex)
{
MessageBox.Show("Exception in CreateDatabase " + ex.ToString(), "Exception in CreateDatabase", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (myConn.State == ConnectionState.Open)
{
myConn.Close();
}
}
}
private void btnDeleteDb_Click(object sender, EventArgs e)
{
string nameToDelete = cbxDb.Text;
string myConnectionString = form1ConnectionString + "AttachDBFileName = " + form1DatabasePath + "\\" + nameToDelete + ".mdf ";
string str = "USE MASTER DROP DATABASE " + nameToDelete;
SqlConnection myConn = new SqlConnection(myConnectionString);
SqlCommand myCommand = new SqlCommand(str, myConn);
myConn.Open();
try
{
myCommand.ExecuteNonQuery();
MessageBox.Show("DataBase '" + nameToDelete + "' was deleted successfully");
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString(), "Exception in DeleteDatabase '" +nameToDelete+ "'", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (myConn.State == ConnectionState.Open)
{
myConn.Close();
}
}
}
private void btnDoesDbExist_Click(object sender, EventArgs e)
{
string nameToTest = cbxDb.Text;
using (var connection = new SqlConnection(form1ConnectionString))
{
using (var command = new SqlCommand(string.Format(
"SELECT db_id('" +nameToTest+ "')", nameToTest), connection))
{
connection.Open();
if ((command.ExecuteScalar() != DBNull.Value))
{
MessageBox.Show("DataBase '" +nameToTest+ "' exists");
}
else
{
MessageBox.Show("Database '" +nameToTest+ "' does not exist");
}
}
}
}
}
}
Thank you to all for replies, and your trouble is greatly appreciated.
I now understand that I'm using the wrong database so I've tried to use SQL Server Compact instead. Have uninstalled, downloaded again, and reinstalled SQL Server Compact including SP1. Have also downloaded and installed SQL Server Compact/SQLite Toolbox from https://visualstudiogallery.msdn.microsoft.com/0e313dfd-be80-4afb-b5e9-6e74d369f7a1 . But Visual Studio has throughout shown an error when I type using System.Data.SqlServerCe . Also when I type SqlCeEngine or SqlCecommand, I assume for the same reason.
In Visual Studio, SQL Server Data Tools and SQL Server Compact & SQLite Toolbox are shown as installed products, but not SQL Server Compact. Do I need to install this into Visual Studio, and if so how is it done?
In Solution Explorer under References, check that System.Data.SqlServerCe is listed. If not, right click on References then Add Reference -> Browse button and select the file System.Data.SqlServerCe.dll, probably in C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop. System.Data.SqlServerCe should now appear under References.
The program below appears to work, and is much simpler. Thanks to all for assistance.
using System;
using System.Data;
using System.Windows.Forms;
//my additions
using System.Data.SqlServerCe;
using System.IO;
namespace DataProg15
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static string form1DatabasePath = "C:\\DbTemp\\dbtemp1.sdf";
public static string form1ConnectionString = "Data Source = " +form1DatabasePath;
private void btnCreateDb_Click(object sender, EventArgs e)
{
SqlCeEngine engine = new SqlCeEngine(form1ConnectionString);
try
{
engine.CreateDatabase();
MessageBox.Show("DataBase '" +form1DatabasePath+ "' was created successfully");
}
catch (System.Exception ex)
{
MessageBox.Show("Exception in CreateDatabase " + ex.ToString(), "Exception in CreateDatabase", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
engine.Dispose();
}
}
private void btnDeleteDb_Click(object sender, EventArgs e)
{
if (File.Exists(form1DatabasePath))
{
try
{
File.Delete(form1DatabasePath);
MessageBox.Show("DataBase '" +form1DatabasePath+ "' was deleted successfully");
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString(), "Exception in DeleteDatabase '" +form1DatabasePath+ "'", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
private void btnDoesDbExist_Click(object sender, EventArgs e)
{
if (File.Exists(form1DatabasePath))
{
MessageBox.Show("DataBase '" +form1DatabasePath+ "' exists");
}
else
{
MessageBox.Show("DataBase '" +form1DatabasePath+ "' does not exist");
}
}
}
}
SQL Server will not let you delete the physical files of a database if that database is active - EVER. The only you would ever be able to do this is if the database is DETACHED ( as mentioned earlier )
So I suspect something your telling us isn't quite right ??
I would change your "check database exists" logic to be;
select * from sys.databases where name = 'yourdatabasename'
I would run this query anyway when you have deleted your database, just to see what it returns.
Related
I am trying to update a column contains below value:
\\localhost\db\kkk\086018\ss\DocA\1_216925.jpg
with
\\localhost\db\kkk\086018\dd\DocA\1_216925.jpg
by using below C# code:
string str = "update my_document " +
"set path = replace (path,'" + fromFolder + "','" + toFolder + "')" +
"where doc_id in( select doc_id from patient_document where folder_id='" + id + "')";
str.Replace("\\", "\\\\");
Console.WriteLine(str);
using (MySqlConnection conn = new MySqlConnection(ECModel.Instance.ConnString))
{
using (MySqlCommand cmd = new MySqlCommand(str, conn))
{
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
}
what I observe that path submitting correctly to mysql but it wont reflect since between C# application and mysql, all the \\ convert to \ .
Would you mind advice me how to solve my issue?
I used # in front of my str also but that solution also didn't work.
** also I notice when I run my update statement with \\\\ it is working fine.
To try to keep this simple, I think the problem you're having is you effectively need both the "#" and the escape values. Try something like this. It worked for me. I made some assumptions on the data structures, and tested this on SQL Server, not MySQL, but I think the concept is sound and I reverted the code back to the MySQL client for you.
class Program
{
static void Main(string[] args)
{
Program program = new Program();
program.updateTable("1", #"\\share\from\path", #"\\share\to\path");
Console.ReadLine();
}
private void updateTable(string id, string fromFolder, string toFolder)
{
string str = #"update my_document " +
"set path = replace (path,'" + fromFolder + "','" + toFolder + "')" +
"where doc_id in( select doc_id from patient_document where folder_id='" + id + "')";
str.Replace("\\", "\\\\");
Console.WriteLine(str);
using (MySqlConnection conn = new MySqlConnection(ECModel.Instance.ConnString))
{
using (MySqlCommand cmd = new MySqlCommand(str, conn))
{
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}
I have created a simple application every thing is working fine except update
portion insertion is working fine with same table data
My code is
private void button2_Click(object sender, EventArgs e)
{
string cmd = ("UPDATE submissionFee SET [stdName]='" + textBox2.Text + "', [fatherName]='" + textBox3.Text + "', [program]='" + textBox4.Text + "', [adress]='" + textBox5.Text + "',[email]='" + textBox6.Text + "', [cellNum]='" + textBox7.Text + "', [isPaid] = '" + textBox8.Text + "', [SubmissionDate] = '" + dateTimePicker1.Value.ToString("MM/dd/yyyy") + "'Where [ID]='" + textBox1.Text + "'");
try
{
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = cmd;
command.ExecuteNonQuery();
MessageBox.Show("Account Has Been Updated");
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
MessageBox.Show("Please Enter Valid Data");
}
}
Error Screenshot
Probably the connection is already open when you try to open it.
Either:
1) Make sure you close the connection from the last time you used it.
2) Or, if it is sometimes supposed to be kept open, check if the connection is already open, and don't close it if it is. Something like:
bool bWasOpen = (connnection.State == ConnectionState.Open);
if (!bWasOpen)
connection.Open();
...
if (!bWasOpen)
connection.Close();
Much Worse than the crash: Your code is volunerable to Sql-injection.
--> Use parameterized sql.
The reason for this exception in the dialog is due to the connection state is already open; and hence it cannot be opened again. You must close the connection in your previous statement. Or, check if the connection closed, and then open it.
Some other tips to you is
Do not use Textbox1, Textbox2 etc., give them proper ID like txtStudentId, txtFatherName etc.,
User SQL Parameters to pass the values to your database. check the sample statements below
String query = "UPDATE submissionFee SET stdName=#stdName, fatherName=#fatherName where id=#id;";
SqlCommand command = new SqlCommand(query, db.Connection);
command.Parameters.Add("#id",txtID.txt); command.Parameters.Add("#stdName",txtStudent.Text); command.Parameters.Add("#fatherName",txtFatherName.Text);
command.ExecuteNonQuery();
Please use using statement when You query to database.
Why? Simple... it has implemented IDisposable.
P.S.
Use parameterized query to protect against SQL Injection attacks.
string insertStatement = UPDATE submissionFee SET stdName=#stdName,fatherName=#fatherName,program=#program,adress=#adress,email=#email,cellNum=#cellNum,isPaid=#isPaid,SubmissionDate=#SubmissionDate,ID=#ID
using (OleDbConnection connection = new OleDbConnection(connectionString))
using (OleDbCommand command = new OleDbCommand(insertStatement, connection))
command.Parameters.AddWithValue("#ID",textBox1.Text);
command.Parameters.AddWithValue("#stdname",textbox2.Text);
command.Parameters.AddWithValue("#fathername",textBox3.Text);
command.Parameters.AddWithValue("#program",textBox4.Text);
command.Parameters.AddWithValue("#adress",textBox5.Text);
command.Parameters.AddWithValue("#email",textBox6.Text);
command.Parameters.AddWithValue("cellNum",textBox7.Text);
command.Parameters.AddWithValue("#isPaid",textBox8.Text);
command.Parameters.AddWithValue("#SubmissionDate",dateTimePicker1.Value.ToString("MM/dd/yyyy"));
connection.Open();
var results = command.ExecuteNonReader();
}
}
Part of code was taken from this link.
I have faced a problem to update a row in SQL Serve 2008 via C#. NET application.
During runtime, the application tries to update the database but with no success. However, there is no exception, error, NOTHING. Checking the SQL Profile, the update command was sent, but not committed.
If I run the application debugging it step-by-step (via 'F11') the row is updated successfully (!?!?!?!?!)
I have copied the SQL update command and ran it on SQL Management Studio and also worked fine.
General Information:
- The only problem is in runtime mode.
- The user used is 'sa' with all granted permission
- I have ran the SAME METHODS for other tables (the only thing that changes is the table name) and it works fine.
The method responsible for it is:
public void Save(FormaResult obj)
{
try
{
bool insert = GetById(obj.SLABID) == null;
IList<string> colResult = GetColumns(TABLE);
List<string> colList = colResult.Where(TableColumns.Contains).ToList();
if (insert)
{
string col = string.Join(",", colList.Select(i => i).ToArray());
string colParam = string.Join(", ", colList.Select(i => "#" + i).ToArray());
QueryString = "INSERT INTO " + TABLE + " (" + col + ") VALUES(" + colParam + ");";
}
else
{
string colSet = string.Join(", ", colList.Select(i => i + " = #" + i).ToArray());
QueryString = "UPDATE " + TABLE + " SET " + colSet + " WHERE SLABID = #Id1;";
}
DbCommand = Conn.CreateCommand();
DbCommand.Connection = Conn;
DbCommand.CommandText = QueryString;
ListDbParameters = new List<DbParameter>
{
this.CriarParametro<DateTime>("GT_TIME", obj.GT_TIME),
this.CriarParametro<long?>("SLABID", obj.SLABID),
this.CriarParametro<short?>("STATUS", obj.STATUS)
};
if (!insert)
{
ListDbParameters.Add(this.CriarParametro<long>("Id1", obj.SLABID));
}
foreach (DbParameter param in ListDbParameters)
{
DbCommand.Parameters.Add(param);
}
Conn.Open();
DbCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
TrkCGManagedModuleService.Logger.Error(ex.Message);
throw;
}
finally
{
Conn.Close();
}
}
I have also used this method:
public void OkEvt()
{
try
{
this.QueryString = "UPDATE " + TABLE + " SET STATUS = 1 " +
"FROM (SELECT TOP(1) * FROM " + TABLE + " WHERE STATUS=0 ORDER BY GT_TIME ASC) I " +
"WHERE " + TABLE + ".SLABID = I.SLABID AND " + TABLE + ".STATUS=0 AND " + TABLE + ".GT_TIME = I.GT_TIME;";
this.DbCommand = this.Conn.CreateCommand();
this.DbCommand.Connection = this.Conn;
this.DbCommand.CommandText = this.QueryString;
this.Conn.Open();
this.DbCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
TrkCGManagedModuleService.Logger.Error(ex.Message);
throw;
}
finally
{
this.Conn.Close();
}
}
Both methods have the same aim, update the column 'STATUS' to '1'.
I would say the same thing as Soner Gonul about the SQL injection. I understand what your trying to do, but from my experience your leaving open a security door that is easily closed. Just requires a bit more time writing your CRUD statements for each table.
Here is a code sample that I use for my update queries you might find useful. If you are going to use this method, remember to create a user that has deny reader and deny writer. Then run a command to grant them execute permissions on all stored procedures.
this.o_ConnectionString is a private variable set inside my class constructor since i put my data layer in a separate project than my web applications.
public int UpdateThisTable(int TableUID, string SomeField)
{
string StoredProcedure = "usp_SomeStoredProcedure";
SqlConnection conn = new SqlConnection(enteryourconnectionstring);
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#TableUID", TableUID);
cmd.Parameters.AddWithValue("#SomeField", SomeField);
conn.Open();
int rowsaffected = cmd.ExecuteNonQuery();
conn.Close();
return rowsaffected;
}
im trying to store som data into mysql database on localhos
but i got this message:
Login field for user 'root
im sure about the uid and pws are right.
private void button1_Click_1(object sender, EventArgs e)
{
String connection = "server=localhost; user =root; Pwd=password;database=skradderi;";
SqlConnection conn = new SqlConnection(connection);
SqlCommand cmd = new SqlCommand("INSERT INTO kunder(Namn ,Adress ,telfon ,OrgNr)VALUES ('" + txtboxName.Text + "','" + txtboxAdress.Text + "','" + txtboxPostNr.Text + "','" + txtOrgNr.Text + "')");
try
{
conn.Open();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
I found out why it wasnt working.
The connection String is for Mysql, but im using Sql connection.
the right connection string is :
" Data Source=ENTERPRISE-PC;Initial Catalog=skradderi;Integrated Security=True ";
I've spent a lot of time trying to research outside resources, but different solutions seem to be more involved than I was hoping.
I am trying to achieve the following:
create simple database on existing SQL instance on this local computer.
security should just be a simple user name and password
other options are unnecessary (log, growth, max size, etc)
This is my first attempt at database integration with my program. using SQLite or SMO seemed slightly overwhelming to start. I've been trying to modify this sample code to work:
private void createDatabase()
{
String str;
SqlConnection myConn = new SqlConnection("Server=" + serverName + ";Integrated security=SSPI;database=master");
str = "CREATE DATABASE " + dbName + " ON PRIMARY " +
"(NAME = " + dbName + "_Data, " +
"FILENAME = 'C:\\" + dbName + ".mdf', " +
"SIZE = 2MB, MAXSIZE = 10MB, FILEGROWTH = 10%) " +
"LOG ON (NAME = " + dbName + "_Log, " +
"FILENAME = 'C:\\" + dbName + ".ldf', " +
"SIZE = 1MB, " +
"MAXSIZE = 5MB, " +
"FILEGROWTH = 10%)";
SqlCommand myCommand = new SqlCommand(str, myConn);
try
{
myConn.Open();
myCommand.ExecuteNonQuery();
MessageBox.Show("DataBase is Created Successfully", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (myConn.State == ConnectionState.Open)
{
myConn.Close();
}
}
}
Any ideas on how to create a simple query string or something to create a database? If there's a better way, that's fine but keep in mind I'm trying to keep it as simple as possible just to start with.
Using SMO:
Server server = new Server("servername");
Database db = new Database(server, "MyDatabaseName");
db.Create();
To build an SMO application, you need to reference the SMO assemblies. Click ‘Add Reference’ and navigate to the folder
C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies
Add references to these assemblies:
Microsoft.SqlServer.ConnectionInfo.dll
Microsoft.SqlServer.Smo.dll
Microsoft.SqlServer.Management.Sdk.Sfc.dll
Microsoft.SqlServer.SqlEnum.dll
Add this using statement to the file containing the above code:
using Microsoft.SqlServer.Management.Smo;
On a Side Note:
Fixing Slow SQL Server Management Objects (SMO) Performance