I've been following the tutorial at http://www.codeproject.com/Articles/43438/Connect-C-to-MySQL on connecting my C# application to an SQL database, but I'm not quite clear on how to actually invoke the connection from within my MainWindow.
I've instantiated the object of the class in my main program, to execute the constructor, but I'm not sure on whether or not my connection is being established, or how to go about doing so. Would really appreciate someone pointing me in the right direction.
My code so far:
DbConnect.cs
namespace SpeedyRent
{
internal class DbConnect
{
private SqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
// Constructor
public DbConnect()
{
Initialize();
}
// Initialize values
private void Initialize()
{
server = "localhost";
database = "rent";
uid = "root";
password = "password123";
string connectionString = "SERVER=" + server + ";" + "DATABASE=" +
database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";";
connection = new SqlConnection(connectionString);
}
// Open connection to database
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
}
// Close connection
private bool CloseConnection()
{
try
{
connection.Close();
return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
}
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CurrentDateTimeTextBlock.Text = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss");
var dbConnectObject = new DbConnect();
}
}
I believe the documentation you need is here: http://msdn.microsoft.com/en-us/library/system.data.common.dbconnection%28v=vs.110%29.aspx but in order to open a connection you would do dbConnectObject.open(); and then do whatever you need to do and close with dbConnectObject.close();
Related
I want to access the openConnection from my dbconnect class from by other form but it does not work properly. I have to copy-paste the entire Oopenconnection to the other page for them to access it.
class dbconnect
class DB_Connect
{
private MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
//Constructor
public DB_Connect()
{
Initialize();
}
//Initialize values
private void Initialize()
{
server = "localhost";
database = "xyz";
uid = "root";
password = "";
string connectionString = $"datasource=127.0.0.1;port = 3306; SERVER={server}; DATABASE={database}; USERNAME={uid}; PASSWORD={password};sslmode=none";
connection = new MySqlConnection(connectionString);
}
//open connection to database
public bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch (MySqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show("Cannot connect to server. Contact administrator");
break;
case 1045:
MessageBox.Show("Invalid username/password, please try again");
break;
}
return false;
}
}
//Close connection
public bool CloseConnection()
{
try
{
connection.Close();
return true;
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
}
MyForm 2
On click data is being displayed on dataGridView
private void display_record_Click(object sender, EventArgs e)
{
DB_Connect connect = new DB_Connect(); // I believe this part does not work
string show_query = "SELECT * FROM testing_tb";
if (connect.OpenConnection() == true)
{
using (MySqlCommand cmd_DB = new MySqlCommand(show_query, connection))
{
try
{
using (MySqlDataReader reader = cmd_DB.ExecuteReader())
if (reader.HasRows)
{
dt = new DataTable();
dt.Load(reader);
dataGridView1.DataSource = dt;
}
else
{
MessageBox.Show("No data record detected");
}
connect.CloseConnection();
}
catch (Exception ex)
{
MessageBox.Show("Could not connect to database!\n" + ex, "Database Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}// end of catch
} // end of MySQLCommand
} // end of connection check
}
I want to access data from my dtconnect class so that I do not have to paste public bool OpenConnection(){} in every new form that I want to open connection.
Error: could not connect to database, connection must be valid and open, etc..
If you really want the connection available everywhere you can use this:
public static class Connection
{
private const string ConnectionString = "YOUR CONNECTION";
public static System.Data.SqlClient.SqlConnection Conn { get; private set; } = null;
public static void Open()
{
try
{
Conn = new System.Data.SqlClient.SqlConnection(ConnectionString);
Conn.Open();
}
catch { System.Windows.MessageBox.Show("Can't connect to the server, please check if you have an internet connection."); }
}
public static void Close() { Conn.Close(); }
}
It is not recommended because your connection will be open at all time so you should do this instead:
public static class Connection
{
private const string ConnectionString = "YOUR CONNECTION";
public static System.Data.SqlClient.SqlConnection Conn { get; private set; } = null;
public static void Create() { Conn = new System.Data.SqlClient.SqlConnection(ConnectionString); }
public static void Open()
{
try { Conn.Open(); }
catch { System.Windows.MessageBox.Show("Can't connect to the server, please check if you have an internet connection."); }
}
public static void Close() { Conn.Close(); }
}
And you open and close your connection when needed.
So basically, when you open your connection when using a query you use Connection.Open() and Connection.Close(). It is now accessible from everywhere if the class is in the using of your forms.
Here's a link about the connection state: https://softwareengineering.stackexchange.com/questions/142065/creating-database-connections-do-it-once-or-for-each-query
I would appreciate some help with async/Task implementation in my Windows Form application.
In this app, I retrieve data from the datacenter SQl server database using WCF services, so part of this code runs on the client and some on the datacenter server where it retrieves the data and returns it. I’d like to optimize the code using async/Task on the clien or server or preferably both. The example code starts with a Windows Form with a button, when the button is clicked it gets a value from the database, displays it and updates a local variable.
I’m not clear if I can simply implement async/Task and Task.Run in the first button click event or whether the code should be cascaded through all methods, or something in between. I'm also not clear on how to handle the wcf service.
I’ve created a simplified example of the code, pretty close to sequentially.
In this code, the return value updates the windows form. I’d like to see how this code is optimized using async/Task await for this purpose and what would be different if the code did not return a value.
public partial class Form1 : Form
{
int returnvalue = 0;
public Form1()
{
InitializeComponent();
}
private void btnGetResult_Click(object sender, EventArgs e)
{
int rowcount = ChangeProductPrice(.05m);
txtResult.Text = rowcount.ToString();
}
private int ChangeProductPrice(decimal priceincrease)
{
int rv = MyData.WebServiceObject.ChangePrice(priceincrease);
UpdateLocalVariables(rv);
return rv;
}
private void UpdateLocalVariables(int rv)
{
returnvalue = rv;
}
}
public static class MyData
{
private static IMyDataWCFService _webserviceobject = null;
public static IMyDataWCFService WebServiceObject
{
get
{
if (_webserviceobject is null)
{
//...code to initialize it
}
return _webserviceobject;
}
}
}
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IMyDataWCFService
{
[OperationContract]
int ChangePrice(decimal priceincrease);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyDataWCFService : IMyDataWCFService
{
private MyDataService _serviceObject = null;
private MyDataService ServiceObject
{
get
{
if (_serviceObject == null)
{
_serviceObject = new MyDataService();
}
return _serviceObject;
}
}
public int ChangePrice(decimal priceincrease)
{
return ServiceObject.ChangePrice(priceincrease);
}
}
public class MyDataService //running on server
{
public int ChangePrice(decimal priceincrease)
{
int rows = 0;
SqlConnection conn = null;
try
{
conn = this.GetSqlConnection();
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = conn;
cmd.CommandText = "mysp_UpdatePrice";
cmd.Parameters.Add(new SqlParameter("#Rate", priceincrease));
conn.Open();
rows = cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
ProcessError(ex);
}
finally
{
if (conn != null)
ReturnSqlConnection(conn);
}
return rows;
}
private SqlConnection GetSqlConnection()
{
//dostuff;
return new SqlConnection();
}
private void ProcessError(Exception ex)
{
//dostuff;
}
private void ReturnSqlConnection(SqlConnection conn)
{
//dostuff;
}
}
I have a class where I have a method that is creating a connection string.I want to access that connection string from other windows,but that isn't working.This is my code so far:
My main login is just calling the method from a class on a button click
private void button_Click(object sender, RoutedEventArgs e)
{
Class1 kl = new Class1();
kl.SQLCon(textBox, textBox_Copy);
}
My class looks like this:
class Class1
{
string user = string.Empty;
string pass = string.Empty;
private string ConString = string.Empty;
public string User { get { return this.ConString; } set { this.ConString = value; } }
public void SQLCon(TextBox tb1,TextBox tb2)
{
user = tb1.Text;
pass = tb2.Text;
if (string.IsNullOrWhiteSpace(user) || string.IsNullOrWhiteSpace(pass))
{
MessageBox.Show("Popuni sva polja");
return;
}
SqlConnection con;
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "DESKTOP";
builder.InitialCatalog = "Manager";
builder.IntegratedSecurity = false;
builder.UserID = user;
builder.Password = pass;
try
{
using (con = new SqlConnection(builder.ToString()))
{
con.Open();
if ((con != null && con.State == System.Data.ConnectionState.Open))
{
ConString = builder.ToString();
MessageBox.Show("Uspesno logovan!" + ConString);
Window1 win = new Window1();
win.ShowDialog();
}
}
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}
}
Now when from the Window1 I call the method to get ConString,I get nothing,blank.The problem is that it is not looking in the SQLCon for the string value,it is looking it as it is defined at the beggining of the class.
I can get this to work with this solution: before calling ShowDialog,I can have a string in the Window1, that I can pass this value, something like win.stringCon = ConString,and this works.But I want to be able to do this:
Window1 code:
private void button_Click(object sender, RoutedEventArgs e)
{
Class1 myClass = new Class1();
string conn = myClass.User;
MessageBox.Show(conn);
}
SOLUTION: You can't do it the way I imagined. But here is what you can do.
You define a string (conString) in the Window1 that will be you connection string.And you put this line before you call win.ShowDialog():
mw.conString = conString;
This way you have the string in your new window.And with one line you can transport the value from Window1 to some other Window that you will open next.
I have to create an automated teller machine app to access a database that contians sample customer records. I am having a problem displaying the account numbers from the accountInformation table (database), in my comboBox. I am pretty sure that I created the database connection correctly, and I thought that the code I have would dispay the numbers in the comboBox, so I'm not sure what the problem is. Is there something in comboBox properties that I need to change?
Here is my code:
using SQLDll;
namespace WindowsFormsApplication14
{
public partial class Form1 : Form
{
private Connection myConnection;
private Statement myStatement;
private ResultSet myResultSet;
String databaseURL = "http://www.boehnecamp.com/phpMyAdmin/razorsql_mysql_bridge.php";
public Form1()
{
InitializeComponent();
try
{
//connect to database
SQL sql = new SQL();
myConnection = sql.getConnection(databaseURL);
//create Statement for executing SQL
myStatement = myConnection.createStatement(databaseURL);
}
catch (Exception)
{
Console.WriteLine("Cannot connect to database server");
}
//close statement and database connection
myStatement.close();
myConnection.close();
}
private void Form1_Load(object sender, EventArgs e)
{
loadAccountNumbers();
}
public void setText(string text)
{
}
//load account numbers to ComboBox
private void loadAccountNumbers()
{
//get all account numbers from database
try
{
myResultSet = myStatement.executeQuery("SELECT accountNumber FROM accountInformation");
// add account numbers to ComboBox
while (myResultSet.next())
{
accountNumberComboBox.Items.Add(myResultSet.getString("accountNumber"));
}
myResultSet.close(); // close myResultSet
}//end try
catch (Exception)
{
Console.WriteLine("Error in loadAccountNumbers");
}
}//end method to loadAccountNumbers
I would recommend putting everything in one method. It is more readable and you can ensure everything gets closed even if an exception occurs.
public partial class Form1 : Form
{
private Connection myConnection;
private Statement myStatement;
private ResultSet myResultSet;
String databaseURL = "http://www.boehnecamp.com/phpMyAdmin/razorsql_mysql_bridge.php";
public Form1()
{
InitializeComponent();
loadAccountNumbers();
}
//load account numbers to ComboBox
private void loadAccountNumbers()
{
SQL sql = new SQL();
using (myConnection = sql.getConnection(databaseURL))
using (myStatement = myConnection.createStatement(databaseURL))
using (myResultSet = myStatement.executeQuery("SELECT accountNumber FROM accountInformation"))
{
// add account numbers to ComboBox
while (myResultSet.next())
accountNumberComboBox.Items.Add(myResultSet.getString("accountNumber"));
}
}
I found out what was wrong. I knew I had to call loadAccountNumbers() somewhere but I wasn't sure where. I placed it in public Form1() and that fixed my problem! Thanks for all the help.
I have 2 classes: MyForm and Database
In MyForm I have a method to change a label text to show error:
public void printError(string text){
label1.Text = text;
}
My Database class needs to access that method too, so I make it static:
public static void printError(MyForm form, string text){
form.label1.Text = text;
}
Now the problem is, how do I call that method from Database class?
This question I found said that I need to pass MyForm into Database's contructor like this:
class MyForm : Form{
Database db;
public Form(){
db = new Database(this);
}
}
class Database{
MyForm form;
public Database(MyForm f){
form = f;
}
...
//then I can access the printError like this
MyForm.printError(form, "You got error");
}
I tried that and it freezes the form. Any other solution?
Thanks
Here is a very simple example of how you can achieve this without your data layer knowing about your UI:
class MyForm : Form
{
Database db;
public Form()
{
db = new Database(this);
}
public void DoSomething()
{
var errors = db.Login("", "");
if (errors.Any())
label1.Text = errors.First(); // Or you can display all all of them
}
}
class Database
{
public List<string> Login(string username, string password)
{
var errors = new List<string>();
if (string.IsNullOrEmpty(username))
errors.Add("Username is required");
if (string.IsNullOrEmpty(password))
errors.Add("Password is required");
[...]
return errors;
}
}
Like #Matthew Ferreira and others have stated the design is not idea, but here's something to get you started.
class MyForm : Form
{
public void SomeMethod()
{
var dataAccess = new Repository();
dataAccess.ExecuteQuery();
if (dataAccess.Exceptions.Any())
{
// display your error messages
form.label1.Text = dataAccess.Exceptions.Select(x => x.ToString());
}
}
}
class Repository
{
private readonly HashSet<Exception> _exceptions = new HashSet<Exception>();
public IEnumerable<Exception> Exceptions
{
get { return _exceptions; }
}
public int ExecuteQuery()
{
var numberOfRecordsAffected = 0;
try
{
// do something
}
catch (Exception ex)
{
// normall catching exceptions is a bad idea
// and you should really catch the exception at the
// layer best equiped to deal with it
_exceptions.Add(ex);
}
// but, for the purpose of this example we might want to add some logic to try the query on another database ????
try
{
// do something
}
catch (Exception ex)
{
_exceptions.Add(ex);
}
return numberOfRecordsAffected;
}
}
You need to look up "seperation of concerns". Its really bad to mix your UI code with you Database Access Layer (DAL). Better to bind the UI to business objects that are populated via a DAL.
To let the UI know about an error you could simply use a delegate.
namespace OperationErrorDelegate
{
public delegate void OperationErrorHandler(Exception ex);
public class DAL
{
public event OperationErrorHandler ReportError;
public void DoDALOperationThatCausesError()
{
try
{
int i = 1;
int j = 0;
int k = i/j;
}
catch (Exception ex)
{
ReportError(ex);
}
}
}
}
Add this code to the form:
using System ;
using System.Windows.Forms;
namespace OperationErrorDelegate
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DAL DAL = new DAL();
DAL.ReportError += new OperationErrorHandler(DAL_OperationErrorProgress);
DAL.DoDALOperationThatCausesError();
}
private void DAL_OperationErrorProgress(Exception ex)
{
label1.Text = ex.Message;
}
}
}
Assuming the OP's requirement is to display an error message in a label, when the credentials are wrong:
private void btn_login_Click(object sender, EventArgs e)
{
MySqlConnection con = new MySqlConnection("server=localhost;uid=root;password=abc;database=mydb");
MySqlCommand cmd = new MySqlCommand("select * from emp where name='" + textBox1.Text + "'and pwd='" + textBox2.Text + "'",con);
con.Open();
MySqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{ //successful
//navigate to next page or whatever you want
}
else
Label1.Text("Invalid userid or password");
con.Close();
}
And if you need error message for wrong data type (the user input string but the database column is Integer), then use validations at client side. You dont need to do it at backend, since that will be a burden.
You can use regular expressions for that in the button_click itself.