Using C# & MySQL - c#

I have been able to interface MySQL with my C# WinForms application with the help of wonderful guides all over the Internet, but I am confused as to which "method" is the standard way of doing so, if ever it does exist. To elaborate, I'll first describe the application that I am developing.
C# Application Overview
My application accepts input from the user, uses DataGridView as the main control for CRUD, and generates Excel reports. Basically, it does the below:
Accept input and insert said data into the database
Retrieve records and display them via DataGridView
Update records using the CellValueChanged event
Delete records
Generate reports using Crystal Reports
Using Objects
What I currently do is to store and retrieve data as objects and use those for all of the above operations. For example:
public class Cat
{
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
private string breed;
public string Breed
{
get { return breed; }
set { breed = value; }
}
public Cat(int id, string breed)
{
this.id = id;
this.breed = breed;
}
}
For me to retrieve data, I do:
public void FillCats()
{
cats = new List<Cat>();
conn.Open();
string query = "SELECT * from cat;";
MySqlCommand cmd = new MySqlCommand(query, conn);
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Cat cat = new Cat(
Convert.ToInt32(reader[0]),
reader[1].ToString(),
);
cats.Add(cat);
}
reader.Close();
conn.Close();
}
Likewise, my create, update, and delete operations are simply variants of the below create function:
public void Insert(DatabaseDriver db)
{
string insert = #"
INSERT INTO cat(id, breed)
VALUES(?id, ?breed);";
db.open();
db.setQuery(insert);
db.setParameter("id", this.id);
db.setParameter("breed", this.breed);
db.executeNonQuery();
db.close();
}
Am I doing this right?
It does work, of course, but I was wondering whether there is a less time-consuming method, perhaps similar to how creating a DBML file would automatically connect your application to your SQL Server database, and even automagically associate every attribute with its corresponding primary key. Before anyone asks, unfortunately, it is not an option for me to use SQL Server.

Check out this answer for a much less-involved way of doing it: Fill Datagridview with MySQL data
As a side note, you can simply call reader.GetInt32(0) and reader.GetString(1) instead of Convert.ToInt32(reader[0]) and reader[1].ToString(). That way you won't get a NullReferenceException when breed is null.

Related

How to fix “Invalid operation on a closed object” exception when trying to Read an OracleDataReader

I'm creating a web API using .Net Core and the Oracle.ManagedDataAccess.Core plugin that accesses an Oracle database to retrieve a Blob field and return it as a byte array. I created a function (getBlobfromDB) that gets the Oracle connection string from an encrypted field on a SQL database, connects and uses an OraleDataReader to retrieve and return the Blob field. But when the OraleDataReader tries to Read the record, I'm getting this exception: "Invalid operation on a closed object".
When you search for this issue, the most relevant answer is this post
However, I'm 100% percent sure that user on the conn string has access since that is the schema owner, and I also tried adding the schema owner to the Select query (SELECT FIELD FROM SCHEMA_OWNER.TABLE WHERE ID = "") getting the same error
So I tried two other things, getting a different VARCHAR field from another table on the same database, still getting the same error; and trying on a different Oracle database and I was able to successfully retrieve the data. I noticed that the Oracle versions on the servers are different, 12.2 for the working one and 11.2 for the non-working, this may be the reason? I don't know what else I can do or try, I'll appreciate any help/advice that you can give me
This is the simplified function
private OracleBlob getBlobfromDB(string sSystem, string sID)
{
string sSQL = String.Empty;
string connString = String.Empty;
OracleConnection oConn = new OracleConnection();
if (string.IsNullOrWhiteSpace(sID) || string.IsNullOrWhiteSpace(sSystem) )
{
return null;
}
sSQL = "SELECT BLOB_FIELD FROM TABLE WHERE ID = " + sID;
connString = getConnectionString(sSystem);
try
{
using (oConn = new OracleConnection(connString))
{
oConn.Open();
OracleCommand oCom = new OracleCommand(sSQL, oConn);
OracleDataReader oDr = oCom.ExecuteReader();
if (oDr.HasRows)
{
//I'm able to reach to this point before getting the exception
oDr.Read();
OracleBlob blob = oDr.GetOracleBlob(0);
// Clean up
oDr.Close();
oDr.Dispose();
oCom.Dispose();
return blob;
}
else
{
// Clean up
oDr.Close();
oDr.Dispose();
oCom.Dispose();
return null;
}
}
}
catch (Exception x)
{
return null;
}
finally
{
oConn.Close();
}
}
With the Oracle.ManagedDataAccess dependency you should not Close() the connection and do not use the using clause. It seems that the dependency itself closes the connection at will.
Remove: using(){} keyword and oConn.Close() from your code.

C# Script - modify to only write to certain database fields

I have the following C# script that takes a configured list of elements and writes the values to our database.
using System;
using System.IO;
using System.Data.SqlClient;
public class Script
{
public static bool ExportData(DataExportArguments args)
{
try
{
var sqlStringTest = new SqlConnectionStringBuilder();
// SERVER/INSTANCE
sqlStringTest.DataSource = "SQL Server";
// DATABASE NAME
sqlStringTest.InitialCatalog = "Database";
sqlStringTest.IntegratedSecurity = false;
sqlStringTest.UserID = "user";
sqlStringTest.Password = "password";
using (var sqlConnection = new SqlConnection(sqlStringTest.ConnectionString))
{
sqlConnection.Open();
using (IExportReader dataReader = args.Data.GetTable()) //Get the main data table
{
while (dataReader.Read()) // Loop through Export data rows
{
using (var sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = #"INSERT INTO [dbo].[Subjects] (
SourceId,
DirectSourceUrl,
Identifier,
Name,
Category)
VALUES (
#SourceId,
#DirectSourceUrl,
#Identifier,
#Name,
#Category)";
sqlCommand.Parameters.AddWithValue("#SourceId", dataReader.GetStringValue("SourceId"));
sqlCommand.Parameters.AddWithValue("#DirectSourceUrl", dataReader.GetStringValue("DirectSourceUrl"));
sqlCommand.Parameters.AddWithValue("#Identifier", dataReader.GetStringValue("Identifier"));
sqlCommand.Parameters.AddWithValue("#Name", dataReader.GetStringValue("Name"));
sqlCommand.Parameters.AddWithValue("#Category", dataReader.GetStringValue("Category"));
sqlCommand.ExecuteNonQuery();
}
}
}
}
}
catch (Exception exp)
{
args.WriteDebug(exp.ToString(), DebugMessageType.Error);
return false;
}
return true;
}
}
The issue is that for each configuration to which I attach this script, the fields can be any combination of the above. For example, in one configuration, I may only be using the Identifier and Name fields, and in another, all 5 fields, and in yet another maybe just 3 of them. Therefore I'm having to manually remove the unused fields from the script for each separate configuration I do to avoid getting an error when running the script.
How would I modify this code so that I don't have to manually remove the fields that aren't being used? It would seem that it would be some form of IF and ELSE IF statements, but I can't think of how it would be done outside of listing every single possible combination of fields?
Assuming your IExportReader has some way to determine if a field exists, you could just do something similar to this (Assuming a method HasField, and all your fields are nullable):
sqlCommand.Parameters.AddWithValue("#SourceId",
dataReader.HasField("SourceId")
? dataReader.GetStringValue("SourceId")
: DBNull.Value);

Pulling in Access Database Entry using C#

I'm trying to figure out how to pull specific Entry lines from an Access Database and into a C# Program.
I'm working with a friend to make a sudoku game. We want to pull different levels of difficulty of puzzles from an access database and into a C# program.
Now my question is: Is there a way to have to program pull the specific lines from the database or would we need to load them all into the program and then have them selected from there? These would be put into a two-dimensional array.
What would be the best way to go about this?
I'm not sure what soduku is, but I'm thinking that you need to query your Access DB. Something like this should get you started.
Class BusLogic
{
public List<string> ListboxItems = new List<string>();
public void PopulateListBoxItems(string userName)
{
string connString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\redgabanan\Desktop\Gabanan_Red_dbaseCon\Red_Database.accdb";
using (OleDbConnection connection = new OleDbConnection(connString))
{
connection.Open();
OleDbDataReader reader = null;
OleDbCommand command = new OleDbCommand("SELECT * from Users WHERE LastName='#1'", connection);
command.Parameters.AddWithValue("#1", userName)
reader = command.ExecuteReader();
while (reader.Read())
{
ListboxItems.Add(reader[1].ToString()+","+reader[2].ToString());
}
}
}
}
You could use a DataReader as well.
http://www.akadia.com/services/dotnet_data_reader.html
You definitely don't want to pull in all data from a Table; you need to somehow Query the data set.

Cache is not getting refreshed in sqldependancy

I want to refresh the data automatically when change to the database is made.
I used this documentation:
And made the code on page load as:
protected void Page_Load(object sender, EventArgs e)
{
conString = "Data Source=MITEJ5-PC\\MITEJTECHONOLY;Initial Catalog=SSISTestDatabase;Integrated Security=SSPI;";
SqlDependency.Start(conString);
using (SqlConnection connection =
new SqlConnection(conString))
{
using (SqlCommand command =
new SqlCommand(GetSQL(), connection))
{
SqlCacheDependency dependency =
new SqlCacheDependency(command);
// Refresh the cache after the number of minutes
// listed below if a change does not occur.
// This value could be stored in a configuration file.
int numberOfMinutes = 1;
DateTime expires =
DateTime.Now.AddMinutes(numberOfMinutes);
Response.Cache.SetExpires(expires);
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.AddCacheDependency(dependency);
connection.Open();
gv.DataSource = command.ExecuteReader();
gv.DataBind();
}
}
}
private string GetSQL()
{
return "select Name,Age,Address from tlbStudent;";
}
But when I run this , and made changes in SQL table data, it is not reflecting it on grid automatically.
Where can I be wrong in above code???
Please help me.
First you need to understand how SqlDependency works. Read The Mysterious Notification for a short introduction. Once you learn that the real feature at work is Query Notifications, you can learn about the restrictions in place for queries using notifications, see Creating a Query for Notification. Once such restriction is:
The projected columns in the SELECT statement must be explicitly stated, and table names must be qualified with two-part names. Notice that this means that all tables referenced in the statement must be in the same database.
For future problems read Troubleshooting Query Notifications.
The problem in
private string GetSQL()
{
return "select Name,Age,Address from tlbStudent;";
}
the table name should be 2 parts ""
private string GetSQL()
{
return "select Name,Age,Address from dbo.tlbStudent;";
}
according to the documentation
The projected columns in the SELECT statement must be explicitly stated, and table names must be qualified with two-part names. Notice that this means that all tables referenced in the statement must be in the same database.

How do I create a picklist in ASP.NET/C#?

All I want to do is a very simple select/picklist with values from a MySQL database.
I'm trying to find a simple solution online (I'm new to C#) and everything I'm finding is very complicated.
All I want to do is generate the <select><option.. etc parts, with all the attributes and values that I want to set.
This seems like it should be very, very easy. Can anyone give me some basic instructions, or point me to a tutorial that shows how to accomplish this?
Currently, I am using MySqlCommand and MySqlDataReader for classes to talk to the database (for another function).
Create a class for the entity you want to display. Ex : If you want to show all states in the dropdown, create State class
public class State
{
public int ID { set;get;}
public string Name { set;get;}
}
Now write a method in which you query the database and get the result to the DataReader, Iterate over the items and set the values a new object of our State class. Add each object to a list (of State class). So your method's return type will be a List of State class object.
public List<State> GetStates()
{
List<State> stateList=new List<State>();
// execute query, read from reader and add to the stateList
// the below code is SqlServer DB specific.
// you need to change the Connection,Command class for it to use with MySql.
using (var con= new SqlConnection("replace your connection string"))
{
string qry="SELECT ID,NAME FROM STATES";
var cmd= new SqlCommand(qry, objConnection);
cmd.CommandType = CommandType.Text;
con.Open();
using (var objReader = cmd.ExecuteReader())
{
if (objReader.HasRows)
{
while (objReader.Read())
{
var item=new State();
item.ID=reader.GetInt32(reader.GetOrdinal("ID"));
item.Name=reader.GetString(reader.GetOrdinal("Name"));
stateList.Add(item);
}
}
}
}
return stateList;
}
Now, have a DropDownList control in your page,
<asp:DropDownList id="states" runat="server" />
Now in the codebehind of this page, you can set the data for the dropdown( possibly in the Page_Load event)
if(!isPostBack)
{
states.DataSource=yourRepositary.GetStates();
states.DataTextField="Name";
states.DataValueField="ID";
states.DataBind();
}
I think what you searching for is something like a DropDownList, it accepts a DataSource, so you can use your already populated MySqlDataReader as it.
Something like this
MySqlDataReader dr = //the code to fill the MySqlDataReader
DropDownList1.DataSource = dr;
You can create the DropDownList in the design of your page.
To show the data you need to set then the values
DropDownList1.DataValueField = "DbField1";
DropDownList1.DataTextField = "DbField2";
Generally, in a list/drop down you got (a) the value that will be selected and (b) its presentation to the user. The first one might be some primary key, the second might be some label which is self-explaining to the user.
Assuming you got a table FOOD like
FoodValue | FoodLabel
---------------
00010 | Sausage
00020 | Eggs
00030 | Cheese
Put a listbox in your ASP.NET view, e.g. listBox1, then
you can read it in the code behind using
MySqlConnection con = new MySqlConnection("YOUR CONNECTION STRING");
MySqlCommand cmd = new MySqlCommand("SELECT FoodValue, FoodLabel FROM FOOD", con);
con.Open();
MySqlDataReader r = cmd.ExecuteReader();
while(r.Read()) {
listBox1.Items.Add(new ListItem(r["FoodLabel"], r["FoodValue"]);
}
con.Close();
But keep in mind this is a quick and dirty approach. In production code, you will need some separation of the presentation and data layer. Use the data source controls to bind your data in a better way.

Categories