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");
Related
Hi im trying to make a notification system. Basically when i add a new row, a notification will be shown on my notificationspage realtime (i use signalR with razor pages asp.net). But for some reason when i get on that page, i get these errors: Unable to cast object of type 'System.DBNull' to type 'System.DateTime'.
at myWebApp.Controllers.SpeedListener.GetAlarmList() in \myWebApp\Controllers\SpeedListener.cs:line 83
at myWebApp.Controllers.SpeedListener.ListenForAlarmNotifications() in \myWebApp\Controllers\SpeedListener.cs:line 43
So apparently theres a problem at the controller.
Here is the code of the controller
namespace myWebApp.Controllers
{
public class SpeedListener :Controller
{
private IHubContext<speedalarmhub> _hubContext;
private IMemoryCache _cache;
public SpeedListener(IHubContext<speedalarmhub> hubContext,IMemoryCache cache)
{
_hubContext = hubContext;
_cache = cache;
}
public static string cs = Database.Database.Connector();
public void ListenForAlarmNotifications()
{
NpgsqlConnection conn = new NpgsqlConnection(cs);
conn.StateChange += conn_StateChange;
conn.Open();
var listenCommand = conn.CreateCommand();
listenCommand.CommandText = $"listen notifytickets;";
listenCommand.ExecuteNonQuery();
conn.Notification += PostgresNotificationReceived;
_hubContext.Clients.All.SendAsync(this.GetAlarmList());
while (true)
{
conn.Wait();
}
}
private void PostgresNotificationReceived(object sender, NpgsqlNotificationEventArgs e)
{
string actionName = e.Payload.ToString();
string actionType = "";
if (actionName.Contains("DELETE"))
{
actionType = "Delete";
}
if (actionName.Contains("UPDATE"))
{
actionType = "Update";
}
if (actionName.Contains("INSERT"))
{
actionType = "Insert";
}
_hubContext.Clients.All.SendAsync("ReceiveMessage", this.GetAlarmList());
}
public string GetAlarmList()
{
List<NotificationModel> not = new List<NotificationModel>();
using var con = new NpgsqlConnection(cs);
{
string query = "Select datumnu, bericht FROM notification";
using NpgsqlCommand cmd = new NpgsqlCommand(query, con);
{
cmd.Connection = con;
con.Open();
using (NpgsqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
not.Add(new NotificationModel { Datenow = ((DateTime) dr["datumnu"]).ToString("yyyy/MM/dd"), Bericht = dr["bericht"].ToString() });
}
}
con.Close();
}
}
_cache.Set("notification", SerializeObjectToJson(not));
return _cache.Get("notification").ToString();
}
public String SerializeObjectToJson(Object notification)
{
try
{
return Newtonsoft.Json.JsonConvert.SerializeObject(notification);
}
catch (Exception) { return null; }
}
private void conn_StateChange(object sender, System.Data.StateChangeEventArgs e)
{
_hubContext.Clients.All.SendAsync("Current State: " + e.CurrentState.ToString() + " Original State: " + e.OriginalState.ToString(), "connection state changed");
}
}
}
If needed here is my hub
namespace myWebApp.Hubs
{
public class speedalarmhub : Hub
{
private IMemoryCache _cache;
private IHubContext<speedalarmhub> _hubContext;
public speedalarmhub(IMemoryCache cache, IHubContext<speedalarmhub> hubContext)
{
_cache = cache;
_hubContext = hubContext;
}
public async Task SendMessage()
{
if (!_cache.TryGetValue("notification", out string response))
{
SpeedListener speedlist = new SpeedListener(_hubContext,_cache);
speedlist.ListenForAlarmNotifications();
string jsonspeedalarm = speedlist.GetAlarmList();
_cache.Set("notification", jsonspeedalarm);
await Clients.All.SendAsync("ReceiveMessage", _cache.Get("notification").ToString());
}
else
{
await Clients.All.SendAsync("ReceiveMessage", _cache.Get("notification").ToString());
}
}
}
}
the table name in postgresql is called 'notification', i have two column called 'bericht' with type varchar and 'datumnu' with type date.
Edit suggested by mjwills
DateTime don't accept null value. Check if the value is null and assigne a default value
while (dr.Read())
{
not.Add(new NotificationModel { Datenow = ((DateTime) dr["datumnu"]).ToString("yyyy/MM/dd"), Bericht = dr["bericht"].ToString() });
}
Become
while (dr.Read())
{
DateTime defaultDateTime = DateTime.Now;
if(dr.IsNull("datumnu")){
defaultDateTime = (DateTime)dr["datumnu"];
}
not.Add(new NotificationModel { Datenow = defaultDateTime, Bericht = dr["bericht"].ToString() });
}
in single line
while (dr.Read())
{
not.Add(new NotificationModel { Datenow = (dr.IsNull("datumnu") ? DateTime.Now : (DateTime)dr["datumnu"]), Bericht = dr["bericht"].ToString() });
}
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.
Good day!
Using visual studio 2012, I have created a Student class with get and set codes, and i need to complete the StudentDAO class to create insert coding that will use to store data to database student table. this action is perform by a windows form button click event.
what i need to create a button click code and then insert into database code,
//Student.cs class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SRSJason
{
class Student
{
private string S_Student_id;
private string S_Full_name;
private DateTime S_Dob;
private string S_Address;
private int S_Contact;
private string S_Username;
private string S_Password;
public Student() //Default constructor
{
}
public Student(string Student_id, string Full_name, DateTime Dob, string Address, int Contact, string Username, string Password) //Overloadign
{
S_Student_id = Student_id;
S_Full_name = Full_name;
S_Dob = Dob;
S_Address = Address;
S_Contact = Contact;
S_Username = Username;
S_Password = Password;
}
public void setID(string Student_id)
{
S_Student_id = Student_id;
}
public string getID()
{
return S_Student_id;
}
public void setName(string Full_name)
{
S_Full_name = Full_name;
}
public string getName()
{
return S_Full_name;
}
public void setDob(DateTime Dob)
{
S_Dob = Dob;
}
public DateTime getDob()
{
return S_Dob;
}
public void setAddress(string Address)
{
S_Address = Address;
}
public string getAddress()
{
return S_Address;
}
public void setContact(int Contact)
{
S_Contact = Contact;
}
public int getContact()
{
return S_Contact;
}
public void setUsername(string Username)
{
S_Username = Username;
}
public string getUsername()
{
return S_Username;
}
public void setPassword(string Password)
{
S_Password = Password;
}
public string getPassword()
{
return S_Password;
}
}
}`
//StudentDAO class (please help me to complete this code)
`class StudentDAO
{
static string constring = "Data Source=JAZE;Initial Catalog=srsjason;Integrated Security=True";
SqlConnection m_con = new SqlConnection(constring);
}`
//button click from the form (please help me to complete this code as well)
private void submitstudent(object sender, EventArgs e)
{
}
please help me to complete this coding
First of all when you create private properties u cant access them in your forms, you have to create a method instead inside the same class then use it in your form. second you should know about the ORM - Object Relational Mapping that you are using.
Here I'll list them:
ADO.NET
LINQ to SQL
ADO.NET Entity Framework
When you picked one of those. next step would be learning about how they work and whats the syntax.
However knowing that you kinda showed a syntax of ADO.NET Here is an Example how you can insert the data in your data base using ADO.NET. If you want to add data directly from code-behind without a method. so basically on click event of your button.
private void btn_Click(object sender, EventArgs e)
{
try
{
//create object of Connection Class..................
SqlConnection con = new SqlConnection();
// Set Connection String property of Connection object..................
con.ConnectionString = "Data Source=KUSH-PC;Initial Catalog=test;Integrated Security=True";
// Open Connection..................
con.Open();
//Create object of Command Class................
SqlCommand cmd = new SqlCommand();
//set Connection Property of Command object.............
cmd.Connection = con;
//Set Command type of command object
//1.StoredProcedure
//2.TableDirect
//3.Text (By Default)
cmd.CommandType = CommandType.Text;
//Set Command text Property of command object.........
cmd.CommandText = "Insert into Registration (Username, password) values ('#user','#pass')";
//Assign values as `parameter`. It avoids `SQL Injection`
cmd.Parameters.AddWithValue("user", TextBox1.text);
cmd.Parameters.AddWithValue("pass", TextBox2.text);
//Execute command by calling following method................
//1.ExecuteNonQuery()
//This is used for insert,delete,update command...........
//2.ExecuteScalar()
//This returns a single value .........(used only for select command)
//3.ExecuteReader()
//Return one or more than one record.
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Data Saved");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
con.Close();
}
}
Be sure that you've included your ConnectionString in your config file.
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.
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(); }
}