How can I pass my getters and setters parameters to connection class? - c#

I assigned the textbox inputs to getters and setters also created one connection class. How can I pass my getters and setters parameters to connection class so I can use it inside my mainform.
MemberClass
private string srDatabase = "";
private string srID = "";
private string srPass = "";
public string SDB
{
get
{
return srDatabase;
}
set
{
srDatabase= value;
}
}
public string SID
{
get
{
return srID ;
}
set
{
srID = value;
}
}
public string SPassword
{
get
{
return srPass ;
}
set
{
srPass = value;
}
}
ConnectionClass
class Connection
{
public static OracleConnection GetConnection(string dataSource, string userName, string password)
{
OracleConnection con = null;
if(!string.IsNullOrWhiteSpace(dataSource) && !string.IsNullOrWhiteSpace(userName) && !string.IsNullOrWhiteSpace(password))
{
con = new OracleConnection("Data Source=" + dataSource + ";User Id=" + userName.ToUpper() + ";Password=" + password + ";");
return con;
}
return con;
}
}
MainForm
UserMembers = new UserMembers();
txtSrcUserDatabase.Text = src.srDatabase ;
txtSrcUserID.Text=src.srID.ToUpper();
txtSrcUserPassword.Text = src.srPass;
OracleConnection conn1 = Connection.GetConnection() // **here error**
conn1.Open();
using (OracleCommand Names = new OracleCommand("SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME", conn1))
{
using (OracleDataReader reader = Names.ExecuteReader())
{
while (reader.Read())
{
//Do something
}
}
}

Your method GetConnection requires three parameters. You need to pass them to the method.
UserMembers src = new UserMembers();
src.srDatabase =txtSrcUserDatabase.Text;
src.srID = txtSrcUserID.Text.ToUpper();
src.srPass = txtSrcUserPassword.Text;
OracleConnection conn1 = Connection.GetConnection(src.srDatabase, src.srID, src.srPass)
conn1.Open();
......
Or you could pass the instance of UserMembers to the GetConnection method creating an overload of GetConnection like this
class Connection
{
// the first overload that takes 3 string parameters
public static OracleConnection GetConnection(string dataSource, string userName, string password)
{
....
}
// The second overload that takes an instance of UserMembers
public static OracleConnection GetConnection(UserMembers src )
{
OracleConnection con = null;
if(!string.IsNullOrWhiteSpace(sr.srDatabase) && !string.IsNullOrWhiteSpace(sr.srID) && !string.IsNullOrWhiteSpace(sr.srPass))
{
con = new OracleConnection("Data Source=" + sr.srDatabase + ";User Id=" + sr.srID.ToUpper() + ";Password=" + sr.Pass + ";");
}
return con;
}
}
As a side note. If you need the srID member to be always in upper case then move this logic in the setter property, and you could stop to worry about the proper formatting of this member when you try to read it back
public string SID
{
get { return srID ; }
set { srID = value.ToUpper(); }
}

Related

Truncated incorrect DOUBLE value: 'hello.world'

In my DAO, I have:
public void UpdateProfile(string newName, string newBio, long profileId)
{
using var dbConnection = _databaseProvider.GetConnection();
dbConnection.SetQuery($"UPDATE `profile_data` SET `name` = #newName AND `bio` = #newBio AND `fixed_unicode` = 1 WHERE `profile_id` = #profileId");
dbConnection.AddParameter("newName", newName);
dbConnection.AddParameter("newBio", newBio);
dbConnection.AddParameter("profileId", profileId);
dbConnection.ExecuteQuery();
}
It results in:
Unhandled exception. MySql.Data.MySqlClient.MySqlException (0x80004005): Truncated incorrect DOUBLE value: 'hello.world'
I don't understand why, because the name column is a varchar(255), verified via:
>> SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'profile_data' AND COLUMN_NAME = 'name'
>> varchar
Below I will place code references in my main example, for anyone to check out if it helps debug the issue.
_databaseProvider:
public class DatabaseProvider : IDatabaseProvider
{
private readonly string _connectionString;
public DatabaseProvider(string connectionString)
{
_connectionString = connectionString;
}
public DatabaseConnection GetConnection()
{
var connection = new MySqlConnection(_connectionString);
var command = connection.CreateCommand();
return new DatabaseConnection(connection, command);
}
}
DatabaseConnection:
public class DatabaseConnection : IDisposable
{
private readonly MySqlConnection _connection;
private readonly MySqlCommand _command;
public DatabaseConnection(MySqlConnection connection, MySqlCommand command)
{
_connection = connection;
_command = command;
_connection.Open();
}
public void SetQuery(string commandText)
{
_command.Parameters.Clear();
_command.CommandText = commandText;
}
public int ExecuteQuery()
{
return _command.ExecuteNonQuery();
}
public Task ExecuteQueryAsync()
{
return _command.ExecuteNonQueryAsync();
}
public MySqlDataReader ExecuteReader()
{
return _command.ExecuteReader();
}
public object ExecuteScalar()
{
return _command.ExecuteScalar();
}
public int GetLastId()
{
SetQuery("SELECT LAST_INSERT_ID();");
return int.Parse(ExecuteScalar().ToString());
}
public void AddParameter(string name, object value)
{
_command.Parameters.AddWithValue(name, value);
}
public void Dispose()
{
_connection.Close();
_command.Dispose();
}
}
You UPDATE query is incorrect. Replace AND keyword with a comma.
The query should look like this:
$"UPDATE `profile_data` SET `name` = #newName,
`bio` = #newBio,
`fixed_unicode` = 1
WHERE `profile_id` = #profileId"
Without executing your code, I can notice that your UPDATE command is not correct.
Try this
UPDATE `profile_data` SET `name` = #newName ,`bio` = #newBio ,`fixed_unicode` = 1 WHERE `profile_id` = #profileId");

Multiple database support in C#

My application need to support multiple databases. Currently, it supports Postgres now I am adding support for Orcle and may be SqlServer in upcoming days.
Before asking any question lets look at codes.
IDbParser :
public interface IDbParser
{
IDbConnection GetDbConnection(string ServerName, string DbPortNumber, string Username, string Password, string DatabaseName);
IDbCommand GetDbCommand(string query, IDbConnection sqlConnection);
IDataParameter CreateParameter(string key, object value);
string GetDbQuery(DbQueries query);
}
OracleDbParser :
public class OracleParser : IDbParser
{
#region >>> Queries
private string SELECTGROUPSESSIONS = "....";
........
#endregion
public IDbCommand GetDbCommand(string query, IDbConnection sqlConnection)
{
var command = new OracleCommand();
command.CommandText = query;
command.Connection = (OracleConnection)sqlConnection;
command.CommandType = CommandType.Text;
command.CommandTimeout = 300;
return command;
}
public IDataParameter CreateParameter(string key, object value)
{
return new OracleParameter(key, value);
}
public IDbConnection GetDbConnection(string ServerName, string DbPortNumber, string Username, string Password, string DatabaseName)
{
connString = String.Format("Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS=(PROTOCOL=TCP)(HOST={0})(PORT={1})))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={2}))); Connection Timeout=60; User Id={3};Password={4};",
ServerName, DbPortNumber, DatabaseName, Username, Password);
return new OracleConnection(connString);
}
public string GetDbQuery(DbQueries query)
{
switch (query)
{
case DbQueries.SELECTGROUPSESSIONS:
return SELECTGROUPSESSIONS;
................
..............
default:
return String.Empty;
}
}
}
Similarly, there is parser for Postgres :
public class PostgresParser : IDbParser
{
#region >>> Queries
private string SELECTGROUPSESSIONS = "....";
........
#endregion
public IDbCommand GetDbCommand(string query, IDbConnection sqlConnection)
{
var command = new NpgsqlCommand();
command.CommandText = query;
command.Connection = (NpgsqlConnection)sqlConnection;
command.CommandType = CommandType.Text;
return command;
}
public IDataParameter CreateParameter(string key, object value)
{
return new NpgsqlParameter(key, value);
}
public IDbConnection GetDbConnection(string ServerName, string DbPortNumber, string Username, string Password, string DatabaseName)
{
string connString = String.Format("Server={0};Port={1};Timeout=60;CommandTimeout=300;" +
"User Id={2};Password={3};Database={4};",
ServerName, DbPortNumber, Username, Password, DatabaseName);
return new NpgsqlConnection(connString);
}
public string GetDbQuery(DbQueries query)
{
switch (query)
{
case DbQueries.SELECTGROUPSESSIONS:
return SELECTGROUPSESSIONS;
................
..............
default:
return String.Empty;
}
}
}
DatabaseParserFactory:
public class DatabaseParserFactory
{
public static IDbParser GetDbParser(string dbType)
{
CUCMDbType dbTypeName;
Enum.TryParse(dbType.ToLower(), out dbTypeName);
switch (dbTypeName)
{
case CUCMDbType.oracle:
return new OracleParser();
case CUCMDbType.postgres:
return new PostgresParser();
default:
return new PostgresParser();
}
}
}
Query execution :
public void Query(string queryStatement, DbParameterColl parameters, Action<IDataReader> processReader)
{
using (SqlConnection)
{
IDbCommand selectCommand = null;
selectCommand = _factory.GetDbCommand(queryStatement, SqlConnection);
selectCommand.Parameters.Clear();
using (selectCommand)
{
if (parameters != null)
{
foreach (var param in parameters)
{
selectCommand.Parameters.Add(_factory.CreateParameter(param.Key, param.Value));
}
}
try
{
using (var reader = selectCommand.ExecuteReader())
{
processReader(reader);
}
}
catch (Exception ex)
{
Logger.DebugFormat("Unable to execute the query. Query : {0} . Exception: {1}", queryStatement, ex);
Debug.WriteLine("\n\n>> Error on executing reader. Exception :\n " + ex);
}
}
}
}
FYI: There will only be SELECT queries and no other commands.
I am passing parameter's value as an object. Well, currently there is no problem assigning the parameters and executing the query. But in most of the blogs and in stackoverflow I could see that people have been suggesting to specify the Input direction, and most specifically Input type/DbType. Do I need to specify DbType ? Currently, my code runs fine with no errors. But I am afraid, it might break down in production.
Moreover I have no control over the type of parameter, it could be anything.
So what do you guys suggest? Or is there any better approach of doing this ?
First, you should take a look at DbProviderFactories - most of your code duplicates that already-existing standard functionality. Note that it is not yet available in .NET Core (but will be).
Regarding your question, in general you don't need to specify the parmeter direction - it's assumed to be the default. Database drivers can typically infer the database type from the CLR value you assign to a parameter, but it's a good idea to explicitly specify DbType just to be sure.

Update Collection Value with Database in UWP(MVVM)

I have custom collection which contains student_id,student_name,student_mark.And having the table with same columns in the database as well. The design form have some controls for updating the existing student.
Temporarily all the updating operations are done with that custom collection.Lets assume we have 100 students data in collection and database. Any updating operation should reflect in the collection. But what my doubt is how do i update these values with the database before i close the application??
But when i open the application the collection should have all the values which have stored in the database.
But what my doubt is how do i update these values with the database
Firstly, you need to know how to do CRUD operations on MySQL database with uwp app. For this, please reference this sample.
Secondly, according to your description, you have built up a MVVM project to bind a collection data to the view. But you didn't have a data layer for this MVVM structure. For this, you need to create a class for data layer to do GRUD operations, and establish contact with this data service from ViewModel. More details please reference this article.
The class for data layer I wrote according to your description which contains how to read, update and delete data from mysql database is as follows:
public class Student
{
public int Student_id { get; set; }
public string Student_name { get; set; }
public string Student_mark { get; set; }
}
public class DataService
{
static string connectionString;
public static String Name = "Data Service.";
private static ObservableCollection<Student> _allStudents = new ObservableCollection<Student>();
public static ObservableCollection<Student> GetStudents()
{
try
{
string server = "127.0.0.1";
string database = "sakila";
string user = "root";
string pswd = "!QAZ2wsx";
connectionString = "Server = " + server + ";database = " + database + ";uid = " + user + ";password = " + pswd + ";SslMode=None;";
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand getCommand = connection.CreateCommand();
getCommand.CommandText = "SELECT * FROM student";
using (MySqlDataReader reader = getCommand.ExecuteReader())
{
while (reader.Read())
{
_allStudents.Add(new Student() { Student_id = reader.GetInt32(0), Student_name = reader.GetString(1), Student_mark = reader.GetString(2) });
}
}
}
}
catch (MySqlException sqlex)
{
// Handle it :)
}
return _allStudents;
}
public static bool InsertNewStudent(Student newStudent)
{
// Insert to the collection and update DB
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO student(student_id, student_name, student_mark)VALUES(#student_id, #student_name,#student_mark)";
insertCommand.Parameters.AddWithValue("#student_id", newStudent.Student_id);
insertCommand.Parameters.AddWithValue("#student_name", newStudent.Student_name);
insertCommand.Parameters.AddWithValue("#student_mark", newStudent.Student_mark);
insertCommand.ExecuteNonQuery();
return true;
}
}
catch (MySqlException sqlex)
{
return false;
}
}
public static bool UpdateStudent(Student Student)
{
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "Update student Set student_name= #student_name, student_mark=#student_mark Where student_id =#student_id";
insertCommand.Parameters.AddWithValue("#student_id", Student.Student_id);
insertCommand.Parameters.AddWithValue("#student_name", Student.Student_name);
insertCommand.Parameters.AddWithValue("#student_mark", Student.Student_mark);
insertCommand.ExecuteNonQuery();
return true;
}
}
catch (MySqlException sqlex)
{
// Don't forget to handle it
return false;
}
}
public static bool Delete(Student Student)
{
try
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
MySqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "Delete from sakila.student where student_id =#student_id";
insertCommand.Parameters.AddWithValue("#student_id", Student.Student_id);
insertCommand.ExecuteNonQuery();
return true;
}
}
catch (MySqlException sqlex)
{
return false;
}
}
}
For updating the database in TwoWay binding way, we can implement is by invoking the data updating method in
PropertyChanged event as follows:
void Person_OnNotifyPropertyChanged(Object sender, PropertyChangedEventArgs e)
{
organization.Update((StudentViewModel)sender);
}
For the completed demo you can download here.

C# Error: “Fill: SelectCommand.Connection property has not been initialized.”

I have problem with this error:
C# Error: “Fill: SelectCommand.Connection property has not been
initialized.”
I lloked ower others threads, but people have it built their clients little different and it didnt help.
I dont know, why this error showed. And I suppose its wrong somewhere at SelectOsoba.
I need to show data in DataGridView.
my code is :
class Vrstva
{
public static SqlConnection myConnection;
public static string connstr;
static DataTable t;
public static void createConnect1()
{
connstr = ConfigurationSettings.AppSettings["local1"];
Vrstva.myConnection = new SqlConnection(connstr);
}
public static void createConnect2()
{
connstr = ConfigurationSettings.AppSettings["local2"];
Vrstva.myConnection = new SqlConnection(connstr);
}
public static void createConnect3()
{
connstr = ConfigurationSettings.AppSettings["local3"];
Vrstva.myConnection = new SqlConnection(connstr);
}
public static void openConn()
{
Vrstva.myConnection.Open();
}
public static void closeConn()
{
Vrstva.myConnection.Close();
}
public static SqlDataAdapter Query(string command)
{
return new SqlDataAdapter(command, Vrstva.myConnection);
}
public static void NonQuery(string command)
{
SqlCommand Command = new SqlCommand(command, Vrstva.myConnection);
Command.ExecuteNonQuery();
}
public static bool login1(string login, string password)
{
string login1 = ConfigurationSettings.AppSettings["login1"];
string password1 = ConfigurationSettings.AppSettings["password1"];
if (login == login1 && password == password1)
{
return true;
}
return false;
}
public static bool login2(string login, string password)
{
string login1 = ConfigurationSettings.AppSettings["login2"];
string password1 = ConfigurationSettings.AppSettings["password2"];
if (login == login1 && password == password1)
{
return true;
}
return false;
}
public static bool login3(string login, string password)
{
string login1 = ConfigurationSettings.AppSettings["login3"];
string password1 = ConfigurationSettings.AppSettings["password3"];
if (login == login1 && password == password1)
{
return true;
}
return false;
}
////vypis tabulku prislusniku
public static DataTable SelectOsoba()
{
t = new DataTable();
Query("Select * from Osoba;").Fill(t);
return t;
}
//Insert
public static void PridejOsoba(string Jmeno, string Prijmeni, string Povolani, int Poc_Det)
{
NonQuery("Insert into Osoba(Jmeno,Prijmeni,Povolani,Poc_Det) values('" + Jmeno + "','" + Prijmeni + "','" + Povolani + "','" + Poc_Det + "');");
}
}
This error is most likely being thrown because your connection in this line:
return new SqlDataAdapter(command, Vrstva.myConnection);
has not been initialized.
You have to call one of your createConnectX() methods before trying to query.

Should I use public methods or writeonly properties in my class?

I have a class library that contains a class. The class is responsible to form a connection between the program and the database and provide me with the connection string :
public class DBcon
{
private string pass = "";
private string dbName = "";
OleDbConnection con = new OleDbConnection();
public string setdbName
{
set { dbName = value; }
}
public string setpass
{
set { pass = value; }
}
public OleDbConnection getsetcon
{
set { createcon(); }
get { return con; }
}
private void createcon()
{
PathFinder dbPath = new PathFinder(); // just another class
string DBPath = "";
dbPath.dbFilesPath = "db";
dbPath.setDBName = dbName;
DBPath = dbPath.dbFilesPath;
con.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + DBPath + ";" +
"Persist Security Info = False;Jet OLEDB:Database Password=" + pass + "";
}
}
Firstly, I wanted to use a public method ie. createcon, to avoid all the properties but then I read that's a bad practice.
Then I decided to use write only properties but they are also considered bad practices.
Can anyone tell me what to do to make my class a well structured class. I am using write only properties as I don't want to return strings. I just want the OledbConnection.
Any help will be appreciated even if it changes the structure of the class.
public class DBConnection
{
private string pass = string.Empty;
private string dbName = string.Empty;
private OleDbConnection connection;
public void DBConnection(string dbName, string pass)
{
this.dbName = dbName;
this.pass = pass;
this.Initialize();
}
public OleDbConnection Connection
{
get {return this.connection;}
}
private void Initialize()
{
//all the initialization
var connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + DBPath + ";" +
"Persist Security Info = False;Jet OLEDB:Database Password=" + pass + "";
this.connection = new OleDbConnection(connString);
}
}
p.s. instead of using string concatenation, use appropriate string builder for connection path.

Categories