I've been trying to create a simple registration page and connecting it with database, but when I click on the button to register a new user it returns the following message:
at MappingDatabase.Connection () [0x00016] in <bea5b5103c9f4cfba42ba460a8c4180f>:0
at PersonDatabase.Insert (Person p) [0x00002] in <bea5b5103c9f4cfba42ba460a8c4180f>:0
Here's the code:
using System.Data;
using MySql.Data.MySqlClient;
using System.Configuration;
public static class MappingDatabase
{
public static IDbConnection Connection()
{
MySqlConnection connection = new MySqlConnection(ConfigurationManager.AppSettings["databaseConnection"]);
connection.Open();
return connection;
}
public static IDbCommand Command(string sqlQuery, IDbConnection connection)
{
IDbCommand runCommand = connection.CreateCommand();
runCommand.CommandText = sqlQuery;
return runCommand;
}
public static IDbDataAdapter Adapter(IDbCommand command)
{
IDbDataAdapter adapter = new MySqlDataAdapter();
adapter.SelectCommand = command;
return adapter;
}
public static IDbDataParameter Parameter(string parameterName, object value)
{
return new MySqlParameter(parameterName, value);
}
}
public static class PersonDatabase
{
public static int Insert(Person p)
{
try
{
IDbConnection dbConnection = MappingDatabase.Connection();
IDbCommand dbCommand;
string sql = #"INSERT INTO PER_PERSON VALUES(0, ?name, ?email, ?password);";
dbCommand = MappingDatabase.Command(sql, dbConnection);
dbCommand.Parameters.Add(MappingDatabase.Parameter("?name", p.Name));
dbCommand.Parameters.Add(MappingDatabase.Parameter("?email", p.Email));
dbCommand.Parameters.Add(MappingDatabase.Parameter("?password", p.Password));
dbCommand.ExecuteNonQuery();
dbConnection.Close();
dbCommand.Dispose();
dbConnection.Dispose();
return 0;
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
return -1;
}
}
}
Here's the repository on GitHub
It worked before on a computer running Windows 10.
Could it be a problem with the connector file (MySql.Data.dll)? How can I fix that?
Note: I use Linux Ubuntu 20.04
You can fix this error by downloading the right connector in the hyperlink below:
Download Connector
Related
New to C# programming, I'd like to be able to access MySQL Databases.
I know MySQL connector/NET and MySQL for Visual Studio are required for C# development.
Do I need to install them into my app?
Is it possible I can just release the connector DLL with the program?
Update:
Are both of them required for the end-user or just the connector?
Is there anything else they would need?
Install Oracle's MySql.Data NuGet package.
using MySql.Data;
using MySql.Data.MySqlClient;
namespace Data
{
public class DBConnection
{
private DBConnection()
{
}
public string Server { get; set; }
public string DatabaseName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
private MySqlConnection Connection { get; set;}
private static DBConnection _instance = null;
public static DBConnection Instance()
{
if (_instance == null)
_instance = new DBConnection();
return _instance;
}
public bool IsConnect()
{
if (Connection == null)
{
if (String.IsNullOrEmpty(databaseName))
return false;
string connstring = string.Format("Server={0}; database={1}; UID={2}; password={3}", Server, DatabaseName, UserName, Password);
Connection = new MySqlConnection(connstring);
Connection.Open();
}
return true;
}
public void Close()
{
Connection.Close();
}
}
}
Example:
var dbCon = DBConnection.Instance();
dbCon.Server = "YourServer";
dbCon.DatabaseName = "YourDatabase";
dbCon.UserName = "YourUsername";
dbCon.Password = "YourPassword";
if (dbCon.IsConnect())
{
//suppose col0 and col1 are defined as VARCHAR in the DB
string query = "SELECT col0,col1 FROM YourTable";
var cmd = new MySqlCommand(query, dbCon.Connection);
var reader = cmd.ExecuteReader();
while(reader.Read())
{
string someStringFromColumnZero = reader.GetString(0);
string someStringFromColumnOne = reader.GetString(1);
Console.WriteLine(someStringFromColumnZero + "," + someStringFromColumnOne);
}
dbCon.Close();
}
You can use Package Manager to add it as a package and it is the easiest way. You don't need anything else to work with a MySQL database.
Or you can run this command in Package Manager Console:
PM> Install-Package MySql.Data
NuGet MySql.Data
You must to download MySQLConnection NET from here.
Then you need add MySql.Data.DLL to MSVisualStudio like this:
Open menu project
Add
Reference
Browse to C:\Program Files (x86)\MySQL\MySQL Connector Net 8.0.12\Assemblies\v4.5.2
Add MySql.Data.dll
If you want to know more visit: enter link description here
To use in the code you must import the library:
using MySql.Data.MySqlClient;
An example with connectio to Mysql database (NO SSL MODE) by means of Click event:
using System;
using System.Windows;
using MySql.Data.MySqlClient;
namespace Deportes_WPF
{
public partial class Login : Window
{
private MySqlConnection connection;
private string server;
private string database;
private string user;
private string password;
private string port;
private string connectionString;
private string sslM;
public Login()
{
InitializeComponent();
server = "server_name";
database = "database_name";
user = "user_id";
password = "password";
port = "3306";
sslM = "none";
connectionString = String.Format("server={0};port={1};user id={2}; password={3}; database={4}; SslMode={5}", server, port, user, password, database, sslM);
connection = new MySqlConnection(connectionString);
}
private void conexion()
{
try
{
connection.Open();
MessageBox.Show("successful connection");
connection.Close();
}
catch (MySqlException ex)
{
MessageBox.Show(ex.Message + connectionString);
}
}
private void btn1_Click(object sender, RoutedEventArgs e)
{
conexion();
}
}
}
Looking at the code below, I tried it and found:
Instead of writing DBCon = DBConnection.Instance(); you should put DBConnection DBCon - new DBConnection(); (That worked for me)
and instead of MySqlComman cmd = new MySqlComman(query, DBCon.GetConnection()); you should put MySqlCommand cmd = new MySqlCommand(query, DBCon.GetConnection()); (it's missing the d)
Another library to consider is MySqlConnector, https://mysqlconnector.net/. Mysql.Data is under a GPL license, whereas MySqlConnector is MIT.
private void Initialize()
{
server = "localhost";
database = "connectcsharptomysql";
uid = "username";
password = "password";
string connectionString;
connectionString = "SERVER=" + server + ";" + "DATABASE=" +
database + ";" + "U`enter code here`ID=" + uid + ";" + "PASSWORD=" + password + ";";
connection = new MySqlConnection(connectionString);
}
I have following controller:
public ActionResult delete(int id)
{
//call function
return RedirectToAction("Index");
}
here I want to call following function from my model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MySql.Data.MySqlClient;
namespace project1.Models.Admin
{
public class delete
{
public void delete(int id)
{
//xxx
const string ConnStr = "...";
MySqlConnection connection = new MySqlConnection(ConnStr);
connection.Open();
MySqlCommand sqlcmd2;
sqlcmd2 = connection.CreateCommand();
sqlcmd2.CommandText = "UPDATE `user` SET Aktive = 0 WHERE Nr = #id;";
sqlcmd2.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
sqlcmd2.ExecuteNonQuery();
connection.Close();
//xxx
}
}
}
I get the error that "void" isn't allowed in this context. Is there any other way to call my function here or should I put the whole connection (inside "xxx") into my controller?
Change method name;
public void deleteFunc(int id)
EDIT
Firstly, you should be careful about naming convention. I change your class name like DeleteAction and method name DeleteRecord
public class DeleteAction
{
public void DeleteRecord(int id)
{
//xxx
const string ConnStr = "...";
MySqlConnection connection = new MySqlConnection(ConnStr);
connection.Open();
MySqlCommand sqlcmd2;
sqlcmd2 = connection.CreateCommand();
sqlcmd2.CommandText = "UPDATE `user` SET Aktive = 0 WHERE Nr = #id;";
sqlcmd2.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
sqlcmd2.ExecuteNonQuery();
connection.Close();
//xxx
}
}
Then, you can call desired function by creating an instance from class;
public ActionResult delete(int id)
{
var deleteActionObject = new DeleteAction();
deleteActionObject.DeleteRecord(id);
return RedirectToAction("Index");
}
There are several problems in your code.
First you cannot use delete as both a class- and a member-name. Having said this delete is a really bad name for a class.
Second you should follow naming-conventions, e.g. use PascalCase-names for both methods and classes.
And last and most important, you need an instance of your class of which you want to call the method:
public ActionResult delete(int id)
{
myInstanceOfDeleteClass.delete(id);
return RedirectToAction("Index");
}
If you donĀ“t have an instance of that class, you may also make delete a static one. Then you could directly call the method within your controller:
public ActionResult delete(int id)
{
DeleteClass.Delete(id);
return RedirectToAction("Index");
}
public class DeleteClass
{
public static void Delete(int id)
{
//xxx
const string ConnStr = "...";
MySqlConnection connection = new MySqlConnection(ConnStr);
connection.Open();
MySqlCommand sqlcmd2;
sqlcmd2 = connection.CreateCommand();
sqlcmd2.CommandText = "UPDATE `user` SET Aktive = 0 WHERE Nr = #id;";
sqlcmd2.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
sqlcmd2.ExecuteNonQuery();
connection.Close();
//xxx
}
}
I am trying to use DI with Factory. What I have so far is:
Factory:
public interface IConnectionFactory
{
IDbConnection Create();
}
public class DbConnectionFactory : IConnectionFactory
{
private readonly DbProviderFactory _providerFactory;
private readonly string _connectionString;
public DbConnectionFactory(string connectionString, string providerName)
{
_connectionString = connectionString;
_providerFactory = DbProviderFactories.GetFactory(providerName);
}
public IDbConnection Create()
{
var connection = _providerFactory.CreateConnection();
if (connection != null)
connection.ConnectionString = _connectionString;
return connection;
}
}
public class DbContext
{
private readonly IDbConnection _connection;
public DbContext(IConnectionFactory connectionFactory)
{
_connection = connectionFactory.Create();
}
public IDbCommand CreateCommand()
{
var cmd = _connection.CreateCommand();
return cmd;
}
public void Dispose()
{
_connection.Dispose();
}
}
public static class DbCommandExtensions
{
public static IDbDataParameter CreateParameter(this IDbCommand command, string name, object value)
{
var parameter = command.CreateParameter();
parameter.ParameterName = name;
parameter.Value = value;
return parameter;
}
}
Repository:
public class AgentRepository : IAgentRepository
{
private readonly DbContext _context;
public AgentRepository(DbContext context)
{
_context = context;
}
public bool Exists(string input)
{
using (var command = _context.CreateCommand())
{
command.Connection.Open();
command.CommandType = CommandType.Text;
command.CommandText = #"";
command.Parameters.Add(command.CreateParameter("#input", input));
return (bool)command.ExecuteScalar();
}
}
}
Now, in my client application I would like to pass connection string down to repository. Connection string will be created dynamically from other data source. I also would like to have service layer which pulls data from repository and passes DTO to the client. As DI container I am using Ninject. My question is how client should be implemented and how should configure Factory in Ninject?
-- EDIT 1
To move my project forward I implemented an anti pattern:
Service:
public AgentService(string connectionString)
{
var connectionFactory = new DbConnectionFactory(connectionString, "System.Data.SqlClient");
var context = new DbContext(connectionFactory);
_agentRepository = new AgentRepository(context);
}
Client:
var connectionString = _systemService.GetConnectionString(ip);
var agentService = new AgentService(connectionString);
var exists = agentService.Exists(input);
I know that this is not best practice but I wasn't able to implement it using DI. Please let me know how can I refactor this piece of code as I am going to implement the same for over 30 classes.
-- EDIT 2
I've did dome refactoring and end up with:
// Client:
var connectionString = _systemService.GetConnectionString(ip);
var dbConnectionFactory = new DbConnectionFactory(connectionString, "System.Data.SqlClient");
var agentService = new AgentService(dbConnectionFactory);
var exists = agentService.AgentExists(input);
// Service:
public class AgentService : IAgentService
{
private readonly IAgentRepository _agentRepository;
public AgentService(IDbConnectionFactory connectionFactory)
{
var context = new DbContext(connectionFactory);
_agentRepository = new AgentRepository(context);
}
public bool AgentExists(string input)
{
return _agentRepository.AgentExists(input);
}
}
// Repository:
public class AgentRepository : IAgentRepository
{
private readonly DbContext _context;
public AgentRepository(DbContext context)
{
_context = context;
}
public bool AgentExists(string input)
{
using (var command = _context.CreateCommand())
{
command.Connection.Open();
command.CommandType = CommandType.Text;
command.CommandText = #"";
command.Parameters.Add(command.CreateParameter("#param", input));
return (bool)command.ExecuteScalar();
}
}
}
// Connection Factory:
public class DbConnectionFactory : IDbConnectionFactory
{
private readonly DbProviderFactory _provider;
private readonly string _connectionString;
public DbConnectionFactory(string connectionString, string providerName)
{
_provider = DbProviderFactories.GetFactory(providerName);
_connectionString = connectionString;
}
public IDbConnection Create()
{
var connection = _provider.CreateConnection();
if (connection != null)
connection.ConnectionString = _connectionString;
return connection;
}
}
// DbContext:
public class DbContext
{
private readonly IDbConnection _connection;
public DbContext(IDbConnectionFactory connectionFactory)
{
_connection = connectionFactory.Create();
}
public IDbCommand CreateCommand()
{
var cmd = _connection.CreateCommand();
return cmd;
}
public void Dispose()
{
_connection.Dispose();
}
}
I wonder if it would be possible to replace new operators in Service class with dependency injection. If it is possible how should it be configured using Ninject?
Here I write some code in static methode which is in class file please Help me how can i create instance of static class
public class ConnectionString
{
public static void CreateCommand(string querystring, string connectionString)
{
using(SqlConnection cn = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(querystring, cn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
}
Just call it like this:
string querystring = "Your values here";
string connectionString = "Your values here";
ConnectionString.CreateCommand(querystring, connectionString);
That's it.
Your ConnectionString class can be refactored to implement an interface like this:
public interface IDataAccess
{
void CreateCommand(string querystring, string connectionString);
}
this interface allows us to inject its implementation in the controller that you mentioned in the comments. So your ConnectionString class (renamed to more meaningful name DataAccess) should look like this:
public class DataAccess : IDataAccess
{
public void CreateCommand(string querystring, string connectionString)
{
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
using (SqlCommand cmd = new SqlCommand(querystring, cn))
{
cmd.ExecuteNonQuery();
}
}
}
}
then in your controller / client class you can have the concrete implementation injected at the run time..
public class DataController : Controller
{
private readonly IDataAccess dataAccess;
public DataController(IDataAccess dataAcces)
{
this.dataAccess = dataAcces;
}
public ActionResult ShowData()
{
string querystring = "you t-sql query";
string connectionString = "<you sql connection string>";
this.dataAccess.CreateCommand(querystring, connectionString);
return this.View();
}
}
If you are using MVC and dont know how to resolve the dependencies then refer to this article
Alternatively you can just new up the instance of DataAccess class like this:
public class DataController : Controller
{
private readonly IDataAccess dataAccess;
public DataController()
{
this.dataAccess = new DataAccess();
}
public ActionResult ShowData()
{
string querystring = "you t-sql query";
string connectionString = "<you sql connection string>";
this.dataAccess.CreateCommand(querystring, connectionString);
return this.View();
}
}
I will not recommend this approach as it wont be possible to unit test it.
Hope this helps!
I am a newbie to C# programming, and am trying to get a REST API working. For some reason it is not connecting from iOS, and I wanted to test the SQL connection in order to troubleshoot the connection from that point first. How can I go about testing it? I tried to figure it out, but my understanding of C# is still quite limited.
Here is the code below:
Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<connectionStrings>
<add name="conString" connectionstring="Data Source=10.0.0.1;Initial Catalog=DBName;Password=Password;User ID=UserID;Integrated Security=True;" providername="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
IServiceAPI.CS
using System.Data;
namespace RESTWebAPI
{
// This interface declare the methods need to be implement.
public interface IServiceAPI
{
void CreateNewAccount(string username, string password);
DataTable Getmembers(string username);
bool UserAuthentication(string username, string passsword);
}
}
ServiceAPI.CS
using System;
using System.Data;
using System.Data.SqlClient;
using Web.config;
namespace RESTWebAPI
{
public static bool IsServerConnected(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
return true;
}
catch (SqlException)
{
return false;
}
}
}
public class ServiceAPI : IServiceAPI
{
SqlConnection dbConnection;
public ServiceAPI()
{
dbConnection = DBConnect.getConnection();
}
public void CreateNewAccount(string username, string password)
{
if (dbConnection.State.ToString() == "Closed")
{
dbConnection.Open();
}
string query = "INSERT INTO members VALUES ('" + username + "','" + password + "');";
SqlCommand command = new SqlCommand(query, dbConnection);
command.ExecuteNonQuery();
dbConnection.Close();
}
public DataTable Getmembers(string username)
{
DataTable membersTable = new DataTable();
membersTable.Columns.Add(new DataColumn("username", typeof(String)));
if (dbConnection.State.ToString() == "Closed")
{
dbConnection.Open();
}
string query = "SELECT username FROM members WHERE username='" + username + "';";
SqlCommand command = new SqlCommand(query, dbConnection);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
membersTable.Rows.Add(reader["username"]);
}
}
reader.Close();
dbConnection.Close();
return membersTable;
}
public bool UserAuthentication(string username, string passsword)
{
bool auth = false;
if (dbConnection.State.ToString() == "Closed")
{
dbConnection.Open();
}
string query = "SELECT id FROM members WHERE username='" + username + "' AND password='" + passsword + "';";
SqlCommand command = new SqlCommand(query, dbConnection);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
auth = true;
}
reader.Close();
dbConnection.Close();
return auth;
}
}
}
DBConnect.cs
using System.Configuration;
using System.Data.SqlClient;
namespace RESTWebAPI
{
// This class is used to connect to sql server database
public class DBConnect
{
private static SqlConnection NewCon;
private static string conStr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
public static SqlConnection getConnection()
{
NewCon = new SqlConnection(conStr);
return NewCon;
}
public DBConnect()
{
}
}
}
Handler1.ashx.cs
using JsonServices;
using JsonServices.Web;
namespace RESTWebAPI
{
public class Handler1 : JsonHandler
{
public Handler1()
{
this.service.Name = "RESTWebAPI";
this.service.Description = "JSON API for mobile application";
InterfaceConfiguration IConfig = new InterfaceConfiguration("RestAPI", typeof(IServiceAPI), typeof(ServiceAPI));
this.service.Interfaces.Add(IConfig);
}
}
}
your IsServerConnected method is static, Note: if connection be open and you try to open it then for sure you'll get an exception, I mean for an open connection connection.Open(); raises an exception, so you need a finally block to close the connection after opening it, if the IsServerConnected method is only for checking the connection:
public static bool IsServerConnected(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
return true;
}
catch (SqlException)
{
return false;
}
finally
{
try
{
connection.Close();
}
catch (Exception ex)
{
}
}
}
}