C# Connect to a SQL server CE programmatically - c#

I'm completely new to database programming. I'm working with Visual Studio 2010 and want to create a database programmatically.
So far I've tried to connect to a SQL Server Compact Edition like this:
public class HistoryDBAccess
{
private SqlConnection conn = new SqlConnection();
public HistoryDBAccess()
{
conn.ConnectionString = #"Server=localhost;Integrated security=SSPI;database=master";
string str = "CREATE DATABASE MyDatabase ON PRIMARY " +
"(NAME = MyDatabase_Data, " +
"FILENAME = 'C:\\MyDatabaseData.mdf', " +
"SIZE = 2MB, MAXSIZE = 10MB, FILEGROWTH = 10%) " +
"LOG ON (NAME = MyDatabase_Log, " +
"FILENAME = 'C:\\MyDatabaseLog.ldf', " +
"SIZE = 1MB, " +
"MAXSIZE = 5MB, " +
"FILEGROWTH = 10%)";
SqlCommand myCommand = new SqlCommand(str, conn);
try
{
conn.Open();
myCommand.ExecuteNonQuery();
MessageBox.Show("DataBase is Created Successfully", "MyProgram", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString(), "MyProgram", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (conn.State == System.Data.ConnectionState.Open)
{
conn.Close();
}
}
}
}
The connection in the Ctor fails with the message that a connection could not be established.
Using the database wizard with VS2010 is fine, but how I can see the SQLCe server under windows 7?
Is it somewhere under the control panel and do I need a default password in the connection string?
Many thanks,
Juergen

I think you should add a connection to your database in Your project using Server Explorer(or Database Explorer) Then check your Connection string.

It looks like you are trying to pass the con object before opening the connection.
So Try this and let me know.
public HistoryDBAccess()
{
conn.ConnectionString = #"Server=localhost;Integrated security=SSPI;database=master";
string str = "CREATE DATABASE MyDatabase ON PRIMARY " +
"(NAME = MyDatabase_Data, " +
"FILENAME = 'C:\\MyDatabaseData.mdf', " +
"SIZE = 2MB, MAXSIZE = 10MB, FILEGROWTH = 10%) " +
"LOG ON (NAME = MyDatabase_Log, " +
"FILENAME = 'C:\\MyDatabaseLog.ldf', " +
"SIZE = 1MB, " +
"MAXSIZE = 5MB, " +
"FILEGROWTH = 10%)";
conn.Open();
SqlCommand myCommand = new SqlCommand(str, conn);
try
{
myCommand.ExecuteNonQuery();
MessageBox.Show("DataBase is Created Successfully", "MyProgram", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString(), "MyProgram", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (conn.State == System.Data.ConnectionState.Open)
{
conn.Close();
}
}
}
}

Once you create it, you're probably going to want to interact with it. You should consider using NHibernate. It has a feature called SchemaExport that can drop and create databases as much as you like.
Here's an example using SQL Express, but it's not much different to use Compact Edition. You can get NHibernate installed in your project by opening it in Visual Studio and clicking Project > Manage NuGet Packages, then searching All Online for NHibernate.
public class NHContext
{
protected static Configuration NHConfiguration;
protected static ISessionFactory SessionFactory;
public static void DropDatabase()
{
new SchemaExport(NHConfiguration).Drop(false, true);
}
public static void CreateDatabase()
{
new SchemaExport(NHConfiguration).Create(false, true);
}
protected static Configuration configureNHibernate()
{
var configure = new Configuration();
configure.SessionFactoryName("BuildIt");
configure.DataBaseIntegration(db =>
{
db.Dialect<MsSql2008Dialect>();
db.Driver<Sql2008ClientDriver>();//db.Driver<SqlClientDriver>();
db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
db.IsolationLevel = IsolationLevel.ReadCommitted;
db.ConnectionString = #"Data Source=.\SQLEXPRESS;Persist Security Info=True;Integrated Security=SSPI;Initial Catalog=NHibernate32Test;User Instance=False";
db.Timeout = 10;
// For testing
db.LogFormattedSql = true;
db.LogSqlInConsole = true;
db.AutoCommentSql = true;
});
return configure;
}
public static void Setup()
{
NHConfiguration = configureNHibernate();
HbmMapping mapping = getMappings();
NHConfiguration.AddDeserializedMapping(mapping, "NHibernate32Test");
SchemaMetadataUpdater.QuoteTableAndColumns(NHConfiguration);
SessionFactory = NHConfiguration.BuildSessionFactory();
}
}

Related

Created local database programatically but I cannot create tables in it?

I have been looking for a solution but I couldn't find anything.
I have to create a folder and after that I have to create a database in it by programatically. I have created folder and database but when I want to create a table in it, first I doesn't say anything (I guess it creates) but I cannot see the tables anywhere and if I will try for second time, it says 'There is already an object name like 'table_name' in the database.
And here is my code:
public void CreateFolder(string folderName)
{
int count = 0;
string path = "C:\\Users\\aabbccdd\\Documents\\";
string[] folders = Directory.GetDirectories(path);
foreach (var item in folders)
{
string dosyaAdi = item.Substring(path.Length);
if (dosyaAdi.Length >= folderName.Length)
{
if (folderName == item.Substring(path.Length, folderName.Length))
{
count = count + 1;
}
}
}
public void CreateSqlDatabase(string filename)
{
string databaseName = System.IO.Path.GetFileNameWithoutExtension(filename);
using (var connection = new System.Data.SqlClient.SqlConnection(
"Data Source=.\\sqlexpress;Initial Catalog=master; Integrated Security=true;User Instance=True;"))
{
try
{
try
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText =
String.Format("CREATE DATABASE {0} ON PRIMARY (NAME={0}, FILENAME='{1}')", databaseName, filename);
command.ExecuteNonQuery();
MessageBox.Show("Database başarılı bir şekilde oluşturuldu.", "Database", MessageBoxButtons.OK, MessageBoxIcon.Information);
btn_forward.Visible = true;
command.CommandText =
String.Format("EXEC sp_detach_db '{0}', 'true'", databaseName);
command.ExecuteNonQuery();
command.CommandText = String.Format("IF EXISTS (SELECT * FROM sysobjects WHERE name='cftc_fabrika') alter table cftc_fabrika alter column asuman varchar(100) ELSE create table cftc_fabrika(asuman varchar(100))");
command.ExecuteNonQuery();
}
}
catch (SystemException ex) // Change exception type based on your underlying data provider
{
if (ex.Message.ToLower().Contains("already exists. choose a different database name"))
{
var match = Regex.Match(ex.Message, "LDATABASE '(.*)' already exists.",
RegexOptions.IgnoreCase);
if (match.Success)
{
String dbFileName = match.Groups[1].Value;
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.FileName = String.Format("{0}/Tools/SSEUtil.exe",
Environment.CurrentDirectory);
p.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
p.StartInfo.Arguments = String.Format("-d \"{0}\"", dbFileName);
p.Start();
}
}
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Hata" + ex.ToString());
}
}
}
This way you can create the database and then create the table by using this database Name
String str;
SqlConnection myConn = new SqlConnection ("Server=localhost;Integrated security=SSPI;database=master");
str = "CREATE DATABASE MyDatabase ON PRIMARY " +
"(NAME = MyDatabase_Data, " +
"FILENAME = 'C:\\MyDatabaseData.mdf', " +
"SIZE = 2MB, MAXSIZE = 10MB, FILEGROWTH = 10%) " +
"LOG ON (NAME = MyDatabase_Log, " +
"FILENAME = 'C:\\MyDatabaseLog.ldf', " +
"SIZE = 1MB, " +
"MAXSIZE = 5MB, " +
"FILEGROWTH = 10%)";
SqlCommand myCommand = new SqlCommand(str, myConn);
try
{
myConn.Open();
myCommand.ExecuteNonQuery();
MessageBox.Show("DataBase is Created Successfully", "MyProgram", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString(), "MyProgram", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (myConn.State == ConnectionState.Open)
{
myConn.Close();
}
}
For Table Do this:-
var commandStr= "If not exists (select name from sysobjects where name = 'Customer') CREATE TABLE Customer(First_Name char(50),Last_Name char(50),Address char(50),City char(50),Country char(25),Birth_Date datetime)";
using (SqlCommand command = new SqlCommand(commandStr, con))
command.ExecuteNonQuery();
Blog For you

Handle SQL ExecuteNonQuery errors C#

I have a table with driver's ID, name, surname, etc.
I wrote a method that gets the driver's ID from a textbox and executes a query using the ExecuteNonQuery(); method. It retrieves the driver's data. But if the user enters an ID which isn't in the table, the Winforms get closed.
I'd like to instead show a MessageBox or something similar appear such as an error that the ID doesn't exist. How can I do that?
EDDIT
public string comandoSQLtxtBox(string comando)
{
string datosConexion = "Data Source=JNATARIO-PC;Initial Catalog= viajesDB;Integrated Security=True;";
try
{
using (SqlConnection con = new SqlConnection(datosConexion))
{
con.Open();
SqlCommand comandoCreartabla = new SqlCommand(comando, con);
object scalarobject;
scalarobject = comandoCreartabla.ExecuteScalar();
con.Close();
return scalarobject.ToString();
}
}
catch
{
MessageBox.Show("Ocurrio un error!");
return "0";
}
}
I tried that way which suggested me in comments nad it partialy worked. But I've a Button that call that method "comandoSQLtxtBox" many times!, so i get almos 15 MessageBox. I tried putting this.close(); in catch but it doesn't wok (gives error). ANy tip?
THE CALLS:
//------------------------------------DATOS CHOFER-----------------------------------------
//ID chof
string Id_chofer = sqlTools.comandoSQLtxtBox("SELECT id_chofer FROM viajes WHERE id_viaje=" + Id_viaje);
boxIDChofViajeCurso.Text = Id_chofer;
//Nombre chof
boxNombreChofCurso.Text = sqlTools.comandoSQLtxtBox("SELECT nombre FROM choferes WHERE id_chofer=" + Id_chofer);
//Apellido chof
boxApellChofCurso.Text = sqlTools.comandoSQLtxtBox("SELECT apellido FROM choferes WHERE id_chofer=" + Id_chofer);
//Telefono
boxTlfChofCurso.Text = sqlTools.comandoSQLtxtBox("SELECT telefono FROM choferes WHERE id_chofer=" + Id_chofer);
//Comentarios
boxRichComChofCurso.Text = sqlTools.comandoSQLtxtBox("SELECT comentarios_chofer FROM choferes WHERE id_chofer=" + Id_chofer);
//--------------------------------------DATOS AUTO-------------------------------------------
//ID auto
string Id_auto = sqlTools.comandoSQLtxtBox("SELECT id_auto FROM viajes WHERE id_viaje=" + Id_viaje);
boxIDAutoCurso.Text = Id_auto;
//Marca
boxMarcaCurso.Text = sqlTools.comandoSQLtxtBox("SELECT marca FROM autos WHERE id_auto=" + Id_auto);
//Modelo
boxModeloCurso.Text = sqlTools.comandoSQLtxtBox("SELECT modelo FROM autos WHERE id_auto=" + Id_auto);
//Patente
boxPatenteCurso.Text = sqlTools.comandoSQLtxtBox("SELECT patente FROM autos WHERE id_auto=" + Id_auto);
//Año
boxAnAutoCurso.Text = sqlTools.comandoSQLtxtBox("SELECT año FROM autos WHERE id_auto=" + Id_auto);
//Comentarios
boxRichComAutoCurso.Text = sqlTools.comandoSQLtxtBox("SELECT comentarios_auto FROM autos WHERE id_auto=" + Id_auto);
Put your query in a try/catch block, and show the MessageBox in the catch. Something like, e.g.:
try
{
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();
command.ExecuteNonQuery();
}
}
catch (Exception e)
{
MessageBox.Show("An error occurred: " + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Take your data in one Datatable and if that particular datatable has the data then it will be shown, otherwise you can use:
MessageBox.Show("Your Message");
After this you can close the winform by:
this.close();

How to create database if not exist in c# Winforms

I want to create a database if it does not exist. I am trying to do it with this code but it has errors and I get this message
enter image description here
Please help.
Code:
if(dbex == false)
{
string str;
SqlConnection mycon = new SqlConnection("Server=.\\sqlexpress;initial catalog=Masalehforoshi;Integrated security=SSPI;database=master");
str = "CREATE DATABASE [Masalehforoshi] CONTAINMENT = NONE ON PRIMARY" +
"(NAME=N'Masalehforoshi'," +
#"FILENAME=N'C:\data\Masalehforoshi.mdf' " +
",SIZE=3072KB,MAXSIZE=UNLIMITED,FILEGROWTH=1024KB)" +
"LOG ON (NAME=N'Masalehforoshi_log.', " +
#"FILENAME=N'C:\Masalehforoshi_log.ldf' "+
",SIZE=1024KB,MAXSIZE=2048GB,FILEGROWTH=10%)";
SqlCommand mycommand = new SqlCommand(str, mycon);
try
{
mycommand.Connection.Open();
mycommand.ExecuteNonQuery();
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString(), "myprogram", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
finally
{
if(mycon.State == ConnectionState.Open)
{
mycon.Close();
}
}
}
My Create Database function
public bool CreateDatabase(SqlConnection connection, string txtDatabase)
{
String CreateDatabase;
string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
GrantAccess(appPath); //Need to assign the permission for current application to allow create database on server (if you are in domain).
bool IsExits = CheckDatabaseExists(connection, txtDatabase); //Check database exists in sql server.
if (!IsExits)
{
CreateDatabase = "CREATE DATABASE " + txtDatabase + " ; ";
SqlCommand command = new SqlCommand(CreateDatabase, connection);
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (System.Exception ex)
{
MessageBox.Show("Please Check Server and Database name.Server and Database name are incorrect .", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
finally
{
if (connection.State == ConnectionState.Open)
{
connection.Close();
}
}
return true;
}
return false;
}
My GrantAccess function to allow permission for current app
public static bool GrantAccess(string fullPath)
{
DirectoryInfo info = new DirectoryInfo(fullPath);
WindowsIdentity self = System.Security.Principal.WindowsIdentity.GetCurrent();
DirectorySecurity ds = info.GetAccessControl();
ds.AddAccessRule(new FileSystemAccessRule(self.Name,
FileSystemRights.FullControl,
InheritanceFlags.ObjectInherit |
InheritanceFlags.ContainerInherit,
PropagationFlags.None,
AccessControlType.Allow));
info.SetAccessControl(ds);
return true;
}
Check Database exists function below
public static bool CheckDatabaseExists(SqlConnection tmpConn, string databaseName)
{
string sqlCreateDBQuery;
bool result = false;
try
{
sqlCreateDBQuery = string.Format("SELECT database_id FROM sys.databases WHERE Name = '{0}'", databaseName);
using (SqlCommand sqlCmd = new SqlCommand(sqlCreateDBQuery, tmpConn))
{
tmpConn.Open();
object resultObj = sqlCmd.ExecuteScalar();
int databaseID = 0;
if (resultObj != null)
{
int.TryParse(resultObj.ToString(), out databaseID);
}
tmpConn.Close();
result = (databaseID > 0);
}
}
catch (Exception)
{
result = false;
}
return result;
}
Based on this support article https://support.microsoft.com/en-us/kb/307283 which has a similar database creation script I suggest removing the "CONTAINMENT = NONE" section.
By default, all SQL Server 2012 and later databases have a containment set to NONE.(https://msdn.microsoft.com/en-us/library/ff929071.aspx), so it probably isn't necessary for your script
It is possible that ado .net doesn't support that tsql command, there is a whole other SQL Server Management Objects library available for messing with advance database and schema scripts https://msdn.microsoft.com/en-us/library/ms162169.aspx . I've used it to create missing databases with table definitions etc during application startup.
To simplify things, here is an even shorter solution.
public void CreateDatabaseIfNotExists(string connectionString, string dbName)
{
SqlCommand cmd = null;
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (cmd = new SqlCommand($"If(db_id(N'{dbName}') IS NULL) CREATE DATABASE [{dbName}]", connection))
{
cmd.ExecuteNonQuery();
}
}
}

How to read data from database & write it on a txt file?

I want to retrieve data from the server database using windows services on a text file?Can i do that?How will i do that?I mean i know to create a window service but i am confused with the SQL connection and file writing part where to execute it?i have tried something
class Program
{
static void Main(string[] args)
{
RunSchedule();
}
public static void RunSchedule()
{
string path = Path.GetFullPath("d:\\MyTest") + "\\" + DateTime.Now.ToString("MM_dd_yyyy_HH_mm") + "_Log.txt";
try
{
if (!File.Exists(path))
{
File.Create(path);
SqlConnection conn = new SqlConnection("Data Source=...;Initial Catalog=Test;User ID=s_a;Password=sa56ta112;");
String sql = #"SELECT Id,UserName, Email,Password,CreatedDate
FROM Register";
SqlCommand com = new SqlCommand();
com.CommandText = sql;
//com.Connection = conn;
conn.Open();
StreamWriter tw = File.AppendText("d:\\MyTest");
SqlDataReader reader = com.ExecuteReader();
tw.WriteLine("Id,UserName,Email,Password,CreatedDate");
while (reader.Read())
{
tw.Write(reader["Id"].ToString());
tw.Write(" , " + reader["UserName"].ToString());
tw.Write(" , " + reader["Email"].ToString());
tw.Write(" , " + reader["Password"].ToString());
tw.Write(" , " + reader["CreatedDate"].ToString());
}
tw.WriteLine(DateTime.Now);
tw.WriteLine("---------------------------------");
tw.Close();
reader.Close();
conn.Close();
}
}
catch (Exception ex)
{
string errorLogPath = #"D:\MyTest.txt";
File.AppendAllText(errorLogPath, Environment.NewLine + ex.Message);
}
}
}
am i doing it correct? Please guide me.
while (reader.Read())
{
row = new DataRow();
row.ItemArray = new object[reader.FieldCount];
reader.GetValues(row.ItemArray);
foreach (object item in row.ItemArray)
{
streamWriter.Write((string)item + "\t");
}
streamWriter.WriteLine();
}
If you get "Access to the path 'd:\MyTest' is denied." error than go to the txt file properties in the solution explorer and than change the Copy to output directory property from Do not copy into Copy if newer or Copy always

C# how to check if database is not busy?

My class has a couple of methods going on. The first one is creating a database, that's done. Then, creates stored procedures that is being read from a sql file. then detach that DB. Now it seems that my store procedure query is taking a while to finish and my method to detach is being invoked while the database is busy. So how do I tell if the database is idle. The exception goes "cannot detach the database because it is currently in use"
Methods:
void CreateStoredProcedures(string type)
{
string spLocation = File.ReadAllText("CreateStoredProcedures.sql");
var conn = new SqlConnection(connectionString + ";database=" + type + DateTime.Now.ToString("yyyyMMdd"));
try
{
Server server = new Server(new ServerConnection(conn));
server.ConnectionContext.ExecuteNonQuery(spLocation);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
bool DetachBackup(string type)
{
var conn = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand("", conn);
command.CommandText = #"sys.sp_detach_db '" + type + DateTime.Now.ToString("yyyyMMdd") + "'";
try
{
conn.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
finally
{
if ((conn.State == ConnectionState.Open))
{
conn.Close();
}
}
return true;
}
Click event:
private void btnFullBackup_Click(object sender, EventArgs e)
{
lblStatus.Text = "Starting full backup...";
Execute("FULL");
progressBar.Value = 20;
lblStatus.Text = "Copying tables...";
progressBar.Value = 60;
CopyTables("FULL");
progressBar.Value = 70;
lblStatus.Text = "Creating stored procedures...";
CreateStoredProcedures("FULL");
progressBar.Value = 80;
CheckDBSize(newBackupLocation, "FULL");
progressBar.Value = 100;
MessageBox.Show("Backup was created successfully", "",
MessageBoxButtons.OK, MessageBoxIcon.Information);
lblStatus.Text = "Done";
progressBar.Value = 0;
if (DetachBackup("FULL") == false)
{
DetachBackup("FULL");
}
}
Chances are it's getting hung on its own connection. sp_detach_db's MSDN https://msdn.microsoft.com/en-CA/library/ms188031.aspx has the following suggestion under the section Obtain Exclusive Access:
USE master;
ALTER DATABASE [DBName] SET SINGLE_USER;
You're DetachBackup method will have connect to master, run the ALTER and the sp_detach_db procedure.
You aren't closing the connection in your CreateStoredProcedures method. Put using statements in like I've shown here and it should fix the problem. (Brief using statement explanation from Microsoft.)
Try this code for your methods:
void CreateStoredProcedures(string type)
{
string spLocation = File.ReadAllText("CreateStoredProcedures.sql");
using (var conn = new SqlConnection(connectionString + ";database=" + type + DateTime.Now.ToString("yyyyMMdd")))
{
try
{
Server server = new Server(new ServerConnection(conn));
server.ConnectionContext.ExecuteNonQuery(spLocation);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
} // End of using, connection will always close when you reach this point.
}
bool DetachBackup(string type)
{
using (var conn = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(#"sys.sp_detach_db '" + type + DateTime.Now.ToString("yyyyMMdd") + "'", conn);
try
{
conn.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
} // End of using, connection will always close when you reach this point.
return true;
}
You shouldn't think of it as the database being "busy", but the error message uses good verbage: in use. To find out if the database is currently in use, the most accurate way would be to find out if any sessions have any lock in the particular database, by querying sys.dm_tran_locks. Here is a helper function to return a bool whether or not the database is in use:
bool IsDatabaseInUse(string databaseName)
{
using (SqlConnection sqlConnection = new SqlConnection("... your connection string ..."))
using (SqlCommand sqlCmd = new SqlCommand())
{
sqlCmd.Connection = sqlConnection;
sqlCmd.CommandText =
#"select count(*)
from sys.dm_tran_locks
where resource_database_id = db_id(#database_name);";
sqlCmd.Parameters.Add(new SqlParameter("#database_name", SqlDbType.NVarChar, 128)
{
Value = databaseName
});
sqlConnection.Open();
int sessionCount = Convert.ToInt32(sqlCmd.ExecuteScalar());
if (sessionCount > 0)
return true;
else
return false;
}
}
Note: Make sure your initial catalog in your connection string isn't the database you're trying to make "not in use", as that'll put your current session in the context of the database, not allowing that operation to complete

Categories

Resources