C# creating a database class - c#

i want to create a class that handles all my Database-Stuff so i started with this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
namespace Server
{
class Database
{
private MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
public Database()
{
server = "localhost";
database = "mydb";
uid = "root";
password = string.Empty;
string connectionString = "SERVER=" + server + ";" + "DATABASE = " + database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";";
connection = new MySqlConnection(connectionString);
}
public bool OpenConnection()
{
try
{
connection.Open();
return true;
} catch(MySqlException e)
{
switch (e.Number)
{
case 0:
// Cannot connect to server
break;
case 1045:
// Invalid username / password
break;
}
return false;
}
}
private bool CloseConnection()
{
try
{
connection.Close();
return true;
} catch(MySqlException e)
{
// ex.message
return false;
}
}
}
}
But i don't know how i should handle inserts, updates and selects that they are dynamic to usw. I want to insert strings, dates and integers.. what is the best solution to create an insert, update and select function that can be used from everywhere?

You have two options.
A) Make methods for every possible Select/Insert/Update/Delete within the Database class
or
B) Make a generic Select and Insert/Update/Delete method which takes an sql query (string) and array/list of SqlParameter and then this data is passed to the functions from another class
The Select method should return a DataTable and the Insert/Update/Delete method could return a value to determine success
Personally I much prefer option B.

Related

Request error in C# MySqlCommand, but working in phpMyAdmin

I am trying to make an update on my MySql database, but I don't understand why it doesn't work when executing from MySqlCommand, I have the famous message "check the manual that corresponds to your MySQL server version" (I already have hundreds of queries working correctly, so I guess something is with syntax?).
edit 2 : Here is the part "near " :
'В-513',PRIORITY=1050,QUANTITY_INIT=28,QUANTITY_REMAINING=0,FICHIER='C:\\Actcut3' at line 1'
Here is the update query :
UPDATE launching_order_details SET
ID_LO=1935,
ID_CONTRACT=4228,
ID_PHASE=11765,
ID_ASS=235314,
LIST_REP_ORI='1005817//В-513//235314//В1007//11765//1//30',IS_SUBDETAIL=0,
REF_DETAIL='3201\\1\\В1007\\В-513\\',
NAME='В-513',
PRIORITY=1050,QUANTITY_INIT=28,QUANTITY_REMAINING=0,
FICHIER='C:\\Actcut3.10\\Data\\Parts\\3201\\1\\В1007\\В-513.ini' WHERE ID=27701
Of course I send it in a same line, I just splitted it here for better readability.
If I make a copy/paste of query, then execute it from phpMyadmin, all is working fine.
Edit : C# code :
DBConnect class :
public void Update(string query)
{
if (this.OpenConnection() == true)
{
if (isMySQL)
{
MySqlCommand cmd = new MySqlCommand(query.Replace("[vsteel].", ""), connection);
cmd.ExecuteNonQuery();
this.CloseConnection();
}
else
{
SqlCommand command = new SqlCommand(query, MSconnection);
command.Parameters.Add(new SqlParameter("0", 1));
//command.Connection = this.MSconnection;
command.ExecuteNonQuery();
this.CloseConnection();
}
}
}
public bool OpenConnection()
{
if (isMySQL)
{
try
{
connection.Open();
return true;
}
catch (MySqlException ex)
{
//When handling errors, you can your application's response based
//on the error number.
//The two most common error numbers when connecting are as follows:
//0: Cannot connect to server.
//1045: Invalid user name and/or password.
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;
}
System.Windows.Forms.Application.Exit();
Global.is_restarted = true;
return false;
}
}
else
{
try
{
MSconnection.Open();
return true;
}
catch (MySqlException ex)
{
//When handling errors, you can your application's response based
//on the error number.
//The two most common error numbers when connecting are as follows:
//0: Cannot connect to server.
//1045: Invalid user name and/or password.
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;
}
System.Windows.Forms.Application.Exit();
Global.is_restarted = true;
return false;
}
}
}
RepereLO class :
private void update()
{
this.listRepereOri = this.listRepereOri.OrderBy(x => x.Priority).ThenBy(x => x.ID).ToList();
DBConnect DataBase = new DBConnect();
string query = "UPDATE [vsteel].launching_order_details SET " +
"ID_LO=" + this.launchingOrder.ID + "," +
"ID_CONTRACT=" + this.contract.ID + "," +
"ID_PHASE=" + this.phase.ID + "," +
"ID_ASS=" + this.assembly.ID + "," +
"LIST_REP_ORI=\'" + convertListRepereOriToString() + "\'," +
"IS_SUBDETAIL=" + Convert.ToInt32(this.isSubRepere) + "," +
"REF_DETAIL=\'" + this.refDetail + "\'," +
"NAME=\'" + this.name + "\'," +
"PRIORITY=" + this.priority + "," +
"QUANTITY_INIT=" + this.quantity + "," +
"QUANTITY_REMAINING=" + this.remainingQuantity + "," +
"FICHIER=\'" + Global.ReplaceSpecialCharacters(this.fileName) + "\' " +
"WHERE ID=" + this.id;
DataBase.Update(query);
}
EDIT 2 : Parametirezed query
my DBConnect class
public void UpdateNew(string query, MySqlParameter[] myParamArray)
{
if (this.OpenConnection() == true)
{
using (MySqlCommand cmd = new MySqlCommand(query.Replace("[vsteel].", ""), connection))
{
for (int i = 0; i < myParamArray.Count(); i++)
{
cmd.Parameters.Add(myParamArray[i]);
}
cmd.Prepare();
cmd.ExecuteNonQuery();
}
}
}
In object :
private void update()
{
this.listRepereOri = this.listRepereOri.OrderBy(x => x.Priority).ThenBy(x => x.ID).ToList();
string query = "UPDATE [vsteel].launching_order_details SET " +
"ID_LO=#idLo," +
"ID_CONTRACT=#idContract," +
"ID_PHASE=#idPhase," +
"ID_ASS=#idAss," +
"LIST_REP_ORI=#listRepOri," +
"IS_SUBDETAIL=#isSubdetail," +
"REF_DETAIL=#refDetail," +
"NAME=#name," +
"PRIORITY=#priority," +
"QUANTITY_INIT=#qtyInit," +
"QUANTITY_REMAINING=#qtyRemaining," +
"FICHIER=#fichier" +
" WHERE ID=#id";
MySqlParameter[] listParams = new MySqlParameter[]
{
new MySqlParameter("id", this.id),
new MySqlParameter("idLo", this.launchingOrder.ID),
new MySqlParameter("idContract", this.Contract.ID),
new MySqlParameter("idPhase", this.Phase.ID),
new MySqlParameter("idAss", this.Assembly.ID),
new MySqlParameter("listRepOri", this.convertListRepereOriToString()),
new MySqlParameter("isSubdetail", this.isSubRepere),
new MySqlParameter("refDetail", this.refDetail),
new MySqlParameter("name", this.name),
new MySqlParameter("priority", this.priority),
new MySqlParameter("qtyInit", this.quantity),
new MySqlParameter("qtyRemaining", this.remainingQuantity),
new MySqlParameter("fichier", this.fileName),
};
DBConnect DataBase = new DBConnect();
DataBase.UpdateNew(query, listParams);
}
The actual problem is using string concatenation to construct a query from external input. This leaves the code wide open to SQL injection, conversion errors (what date format? decimal separator?) and ... syntax errors like this. What if Name is O'Reily for example? Or a user entered ' DROP TABLE Students; # ? No amount of escaping or replacing is going to fix the real bug - using string concatenation.
The correct way to do this is to use parameterized queries. This is actually easier than concatenating strings. If you use a library like Dapper, it's as easy as :
string sql=#"UPDATE [vsteel].launching_order_details
SET
ID_LO=#idlo,
ID_CONTRACT=#contract,
ID_PHASE=#phase,
ID_ASS=#assembly,
LIST_REP_ORI=#ori,
IS_SUBDETAIL=#isSubDetail,
REF_DETAIL=#ref,
NAME=#name,
PRIORITY=#priority,
QUANTITY_INIT=#initial,
QUANTITY_REMAINING=#remaining,
FICHIER=#path,
WHERE ID=#id";
using(var connection=new MySqlConnection(...))
{
connection.Execute(sql, new {
id,
idLo=launchingOrder.ID ,
contract=contract.ID,
....,
path=fileName});
}
Without Dapper, the code is a bit more complex but still easier and safer to write than string concatenation and trying to replace characters.
using(var connection=new MySqlConnection)
using (var cmd=new MySqlCommand(query,connection))
{
cmd.Parameters.AddWithValue("#id",this.id);
...
connection.Open();
cmd.ExecuteNonQuery();
}
BTW the DbConnect class has other issues as well. Long-lived database connections are a bug that harms performance and scalability. The locks taken during a connection remain active until it closes, which results in increased blocking for all clients. This happens even in databases with multi-version concurrency like PostgreSQL.
Connections are meant to be opened as late as possible and closed immediately after use. That's why you see all samples and tutorials create connections in a using block. This ensures the connection is close immediately after use.
ADO.NET uses connection pooling to eliminate the cost of opening a new connection, by reseting existing connections. When DbConnection.Close is called, the connection is reset and placed in a connection pool.
Tutorials
Basics of ADO.NET is a short intro to ADO.NET that explains what the various classes do and how they're used.
MySQL's Tutorial: An Introduction to Connector/NET Programming shows how to use ADO.NET with MySQL.
Microsoft's documentation on ADO.NET is almost an entire book that goes in great depth, so you should probably use it only as a reference
Dapper is a micro-ORM library that makes it very easy to map object properties to parameters and results to objects. It can be used with any ADO.NET provider, including MySQL.
With Dapper, one can write code like this :
public class Dog
{
public int? Age { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public float? Weight { get; set; }
public int IgnoredProperty { get { return 1; } }
}
var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = #Age, Id = #Id", new { Age = (int?)null, Id = guid });
And the library will map the Age and Id properties to #Age and #Id. It will also map the Age and Id columns in the results to Dog.Age and Dog.Id

Create an object with values from an mssql database

I have a database with the following tables:
**Camping Spot**
PK - id - int
FK - location_id - int
number - int
capacity - int
**Location**
PK - id - int
name - string
street - varchar
etc.
**Event**
PK - id - int
FK - location_id - int
name - string
datestart - datetime
etc.
I have the following classes
namespace modellen
{
public class Spot
{
public int Id { get; set; }
public int Number { get; set; }
public int Capacity { get; set; }
}
}
and
namespace DAL_laag
{
public class SpotDal
{
List<Spot> spots = new List<Spot>();
private Database database = new Database();
public GiveAvailiableSpots(int event_id)
{
string query = "A query that gets Id, Number and Capacity";
return ?
}
}
I want to get the id, number and capacity values from the table with a mssql query. Then I want to create a new Spot object and add the object to my list of Spots.
I can't figure out what the query would be to get these three value and the code to create a new object with these three values.
How would I do this?
I think your query needs to look something like this.
string query = #"select id,
number,
capacity
from tblCampingSport cs
left join tblLocation l on cs.location_id == l.id
left join tblEvent e on e.location_id = l.id
where e.id = #eventId";
You're call to the db will look something like this:
List<QueryResult> results = new List<QueryResult>();
using(SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
using(SqlCommand cmd = new SqlCommand(query, conn)
{
cmd.Parameters.AddWithValue("#eventId", event_id);
var reader = cmd.ExecuteReader();
if(reader.HasRows())
{
while(reader.Read())
{
QueryResult result = new QueryResult();
result.EventId = (int)reader["id"];
result.Number = (int)reader["number"];
result.Capacity = (int)reader["capacity"];
results.Add(result);
}
}
}
}
Your class to store the results:
class QueryResult
{
int EventId { get; set;}
int Number { get; set;}
int Capacity { get; set;}
}
None of this is tested or even compiled (it was written straight into this textbox), but I think it's a rough outline of how to get what you want from your tables.
Assuming you are using the MySql Libary to connect to your database. You need a class that allows you to connect to the database which looks like the code segment below; I am using the UWP for Windows 10 with c# so the code should work, however, there may be slight changes but nothing major.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using Windows.UI.Popups;
using Walsall_College_Auditor.Classes;
namespace Walsall_College_Auditor.Models
{
class dbConnect
{
private MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
//Constructor
public dbConnect()
{
Initialize();
}
//Initialize values
private void Initialize()
{
//Prevent the application from throwing "windows-1252' is not a supported encoding name."
System.Text.EncodingProvider ppp;
ppp = System.Text.CodePagesEncodingProvider.Instance;
Encoding.RegisterProvider(ppp);
server = "localhost";
database = "your_db_name"; //Put the new database name here
uid = "root"; //Your db Login/Username
password = ""; //Your db login password
string connectionString = "SERVER=" + server + ";" + "DATABASE=" + database + ";"
+ "UID=" + uid + ";" + "PASSWORD=" + password + ";SslMode=None";
connection = new MySqlConnection(connectionString);
}
//open connection to database
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
catch (MySqlException ex)
{
//When handling errors, you can your application's response based
//on the error number.
//The two most common error numbers when connecting are as follows:
//0: Cannot connect to the server.
//1045: Invalid username and/or password.
switch (ex.Number)
{
case 0:
var dialog1 = new MessageDialog("Cannot connect to server. Contact administrator");
dialog1.Title = "Connection Error";
dialog1.ShowAsync();
break;
case 1045:
var dialog2 = new MessageDialog("Invalid username/password, please try again");
dialog2.Title = "Connection Error";
dialog2.ShowAsync();
break;
}
return false;
}
}
//Close connection
private bool CloseConnection()
{
try
{
connection.Close();
return true;
}
catch (MySqlException ex)
{
var dialog = new MessageDialog(ex.Message);
dialog.Title = "Disconnecting Error";
dialog.ShowAsync();
return false;
}
}
There are other methods that I can post if you require them. Personally, I used this Connect c# to MySql to help me develop my methods for querying the database. If you are using windows forms then this will be perfect and if you are using the Universal Windows Platform then you will require a different version of the DLL file and adjustments to your code that are not shown on the provided link.
However to answer your question correctly: The code below exists in the same DB class and the code is a function that returns a list of companies.
public List<company> getSots()
{
string query = "SELECT * FROM tbl_spot"; //Your table name here
List<Spot> dbSpots = new List<Spot>(); //List to store the gathered spots
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
//Create a new company object and populate with a row at a time
Spot x = new Spot();
x.Id = int.Parse(dataReader["id_spot"].ToString());
x.Number = int.Parse(dataReader["number"].ToString());
x.Capacity = int.Parse(dataReader["capacity"].ToString());
dbSpots.Add(x); //Add created Spot to the Spots list
}
dataReader.Close();
this.CloseConnection();
return dbCmpys; //Return the gathered db companies
}
else { return dbCmpys; }
}
As you can see the code creates a list of the object type (in your case Spot), populates it using a loop to cycle through all the database records and returns the list once completed.
To use the function: In another class or form, create a new instance of the DB class, create a list that equals the function; like so:
//Your form code/class
class SpotForm
{
private dbConnect dbConnection = new dbConnect(); //Database connection
private List<Spot> listSpots = new List<Spot>(); //Local list
// Constructor
public SpotForm()
{
listSpots = dbConnection.getSpots();
}
You now will have a list of the Spots from the database to do with as you please such as looping through to gather or manipulate the data.

Populate DataGrid from Mysql Database

First of all I'm new with C# and Visual Studio.
I followed a tutorial on how to populate DataGridView from MySql table.
I checked multiple times for copying mistakes but I didn't find any.
The code is this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
namespace DataGridMain
{
public partial class Form1 : Form
{
private string server;
private string database;
private string uid;
private string password;
private MySqlConnection connection;
private MySqlDataAdapter mySqlDataAdapter;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
server = "localhost";
database = "elphoapp";
uid = "username";
password = "password";
string connectionString;
connectionString = "SERVER=" + server + ";" + "DATABASE=" + database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";";
connection = new MySqlConnection(connectionString);
if (this.OpenConnection() == true)
{
mySqlDataAdapter = new MySqlDataAdapter("select * from users", connection);
DataSet DS = new DataSet();
mySqlDataAdapter.Fill(DS);
dataGridView1.DataSource = DS.Tables[0];
this.CloseConnection();
}
}
private 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;
default:
MessageBox.Show(ex.Message);
break;
}
return false;
}
}
private bool CloseConnection()
{
try
{
connection.Close();
return true;
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
}
}
I can't seem to find a problem and no error is displaying.
As you are new to Visual Studio, my advice is the first thing you must learn is debugging. It will save you a lot of times. In this case, put a breakpoint in your form_load and run the code step by step. You can that way see what is happening, and inspect all the variables. I'm saying this because i can't see any error in your code, so probably you are not even connecting to the database. Debugging your code you may see why
Ok i figured it out!
All i had to do was to call Form1_Load from inside the Form1() function.
Everything seems to be working fine at the moment.
Thanks, C# is full of damn surprises....

Rendering data from MySQL in a WinForms applications

I have an application I'm trying to create, however I'm stuck.
I am trying to access the site's MySQL query within my code.
Right now I am just trying to test it, to make sure it works, but I'm having no luck with that.
I think I'm just overlooking something simple, but I'm not sure. Any help?
class DBConnect
{
private MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;
public List<string>[] list = new List<string>[1];
public DBConnect()
{
Initialize();
}
private void Initialize()
{
server = "localhost";
database = "XXX";
uid = "XXX";
password = "XXX";
string connectionString;
connectionString = "SERVER=" + server + ";" + "DATABASE=" + database
+ ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";";
connection = new MySqlConnection(connectionString);
}
//this will open the connection to MySql
private bool OpenConnection()
{
try
{
connection.Open();
return true;
}
//if there is a problem connecting, display one of the following connections
catch (MySqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show("Cannot connect to server. Contact Admin");
break;
case 1045:
MessageBox.Show("Invalid username/password, please try again");
break;
}
return false;
}
}
//if the connection fails to connect to MySql server, the client will close the connection.
private bool CloseConnection()
{
try
{
connection.Close();
return true;
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message);
return false;
}
}
//Select statement
public List<string>[] Select()
{
int firstNumber = 2058;
**string query = "USE `db_order` SELECT `order_id` FROM `order_address` WHERE order_id=2058";**
//create a list to store the results
list[0] = new List<string>(0);
//Open's connection
if (this.OpenConnection() == true)
{
//creates a command from the query.
MySqlCommand cmd = new MySqlCommand(query, connection);
//creates a data reader, and executes the command.
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
list[0].Add(dataReader["order_id"] + "");
}
//close Data Reader
dataReader.Close();
this.CloseConnection();
//returns list to be displayed
return list;
}
else
{
return list;
}
}
}
Here is the second class (i got rid of anything that isn't a part of the problem):
public partial class Form1
{
private void InitializeComponent()
{
// CustName
//
this.CustName.AutoSize = true;
this.CustName.Location = new System.Drawing.Point(200, 30);
this.CustName.Name = "CustName";
this.CustName.Size = new System.Drawing.Size(137, 13);
this.CustName.TabIndex = 0;
this.CustName.Text = "Customer\'s name goes here" + new DBConnect().list[0];
}
#endregion
}
Update
You add to the list from your DataReader like this
list[0].Add(dataReader["order_id"] + "");
So, which means you have a multi-dimensional (2-dimension to be exact) array of list. Therefore to access that you have to do like Select()[0][0] , check below:
DBConnect() DBCon = new DBConnect();
this.Custname.Text = DBCon.Select()[0].Count>0 ? "Customer\'s name goes here" +DBCon.Select()[0][0].ToString() : "No Customer to show";

Showing the output query?

I'm trying to show the output of the query SELECT * FROM phpbb_topics
I'm running this from a C# console app, using the MySql connector api.
The query works fine when I run it phpmyadmin, and gives me a list of forum topics.
When I run it in the C# app remotely though, it doesn't seem to do anything.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql;
using MySql.Data;
namespace SqlConsoleSlr
{
class Program
{
static void Main(string[] args)
{
MySql.Data.MySqlClient.MySqlConnection mycon =
new MySql.Data.MySqlClient.MySqlConnection(GetConnectionString());
Console.WriteLine(GetConnectionString());
if (mycon.State != System.Data.ConnectionState.Open)
try
{
mycon.Open();
Console.WriteLine("we're in");
}
catch (System.Data.SqlClient.SqlException ex)
{
Console.WriteLine(ex);
}
MySql.Data.MySqlClient.MySqlCommand msc = new MySql.Data.MySqlClient.MySqlCommand("SELECT * FROM `phpbb_topics` ");
Console.WriteLine("completed"); /// gets to here, but doesn't show output of msc
Console.ReadLine();
}
public static string GetConnectionString()
{
string hostname = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;";
string username = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx;";
string dbname = "xxxxxxxxxxxxxxxxxxxxxxxx;";
string password = "xxxxxxxxxxxxxxxxxxxxxxxxxxx;";
string s = "Server=" + hostname + "User=" + username + "Database=" + dbname + "Password=" + password;
return s;
}
}
}
Is there some method I need to call on the query object?
The only one I could find is msc.BeginExecuteReader();, but that doesn't seem to change the execution either.
You will need to create a MYSQL Data Reader object.
MySql.Data.MySqlClient.MySqlDataReader read = msqlCommand.ExecuteReader();
and then you can output the records after you read.read() all of the records.
You have to create an object of MySQL Data Reader then execute the command.
MySql.Data.MySqlClient.MySqlCommand msc = new MySql.Data.MySqlClient.MySqlCommand("SELECT * FROM `phpbb_topics` ");
MySql.Data.MySqlClient.MySqlDataReader read = msqlCommand.ExecuteReader();
if(read != null)
{
//Sample output
while (read.Read())
{
int TopicID = Convert.ToInt32(read["Topic_ID"]);
string TopicName = Convert.ToString(read["Topic_Name"]);
Console.WriteLine(TopicID.ToString() + " : " + TopicName);
}
}

Categories