Fetch Mysql data with Coma after each fetch C# Mysql - c#

I am trying to fetch the data from mysql data base Column where say i have multiple rows data for specific column and i need to include coma after each row fetch.
before it was giving the data when i tried to add coma
Current Output after adding code Response.Write(name.Split(','));
System.String[]System.String[]System.String[]System.String[]System.String[]System.String[]System.String[]System.String[]System.String[]System.String[]System.String[]
My DB
Phone_Number School_id
1 SC1
2 SC1
3 SC1
4 SC1
Expected Output
1,2,3,4
My Fetch Query
string constr = ConfigurationManager.ConnectionStrings["Logging"].ConnectionString;
using (MySqlConnection con = new MySqlConnection(constr))
{
using (MySqlCommand MySqlCommand = new MySqlCommand("SELECT Phone_Number FROM Login where SchoolId='" + SessionManager.SchoolId + "'", con))
{
MySqlCommand.CommandType = CommandType.Text;
con.Open();
MySqlDataReader MySqlDataReader = MySqlCommand.ExecuteReader();
while (MySqlDataReader.Read())
{
string name = MySqlDataReader["FatherFullName"].ToString();
Response.Write(name.Split(','));
}
con.Close();
}
}

String.Split method splits your string with special character or string. This is not what you want.
You can add your Phone_Number values to a List<string> and you can use string.Join(string, IEnumerable<String>) method to generate comma separated values.
var list = new List<string>();
while(MySqlDataReader.Read())
{
string name = MySqlDataReader["FatherFullName"].ToString();
if(!string.IsNullOrEmpty(name))
{
list.Add(name);
}
}
Response.Write(string.Join(",", list)); // 1,2,3,4
You should always use parameterized queries by the way. This kind of string concatenations are open for SQL Injection attacks.
Two things more;
Default value CommandType is Text. You don't need to assign it explicitly.
You don't need to close your connection with con.Close(). Since you used using statement, it does that automatically.

String.Split is used to
split a string into substrings based on the strings in an array
You can use String.Join like this:-
//define a list of string
List<string> phoneNumbers = new List<string>();
while (MySqlDataReader.Read())
{
//add all the phone numbers to the list
string phoneNum = MySqlDataReader["FatherFullName"].ToString();
if(!String.IsNullOrEmpty(phoneNum))
phoneNumbers.Add(phoneNum);
}
//finally use Join method to get expected result
Response.Write(String.Join(",",phoneNumbers));
Also, please note your query is open for SQL Injection attack and you should consider using paramaterized query instead.

Next to the split/join, you can also get the result from MySQL directly:
SELECT GROUP_CONCAT(Phone_Number) FROM Login WHERE SchoolId = 'id';
This returns 1 single row with all phone numbers, seperated by comma's.

Related

Saving results from SELECT query to another table

I have a SQL query generates the results found below it using Visual Studio query window:
SELECT SUM(TaskLength) AS TaskLength
FROM myTable
WHERE EventStartTime BETWEEN '2019/8/17' AND '2019/8/19'
GROUP BY TaskName
ORDER BY TaskLength
The query results window produces the following:
TaskName TaskLength
--------------------------
Idle Time 20
Start Shift 31
Downtime 85
Engineering 120
Part Prep 141
Maintenance 172
Production 417
My C# code below only returns one string representing one column from one row.
using (SqlConnection con = new SqlConnection(_connectionString))
{
string query = #"SELECT SUM(TaskLength) AS TaskLength
FROM myTable
WHERE EventStartTime BETWEEN '2019/8/17' AND '2019/8/19'
GROUP BY TaskName
ORDER BY TaskLength";
using (SqlCommand cmd = new SqlCommand(query, con))
{
con.Open();
object result = cmd.ExecuteScalar();
string totalMinutes = Convert.ToString(result);
}
}
Does the returned cmd.ExecuteScalar object represent the entire resulting table?
If not, is there another way to do this. My thoughts are to save the results to an intermediate table (if it does not already do this) and save that to a .csv file there unless there is a better way.
ExecuteScalar returns only the first column from the first row.
If you have many rows to read then you need to call ExecuteReader and loop on the using the value returned by the SqlDataReader.Read until it returns false.
While looping you store the results of your query in some kind of List creating objects matching the info returned by the reader.
Then, this list can be easily used as DataSource for some kind of User Interface object like a DataGridView or similar or used to write your data into a file or other storage.
// The model that describes the data returned by the query
public class TaskData
{
public string Name {get;set;}
public int Length {get;set;}
}
.....
// Where you store each record retrieved by the query
List<TaskData> results = new List<TaskData>();
using (SqlConnection con = new SqlConnection(_connectionString))
{
// Added the taskname to the query
string query = #"SELECT TaskName, SUM(TaskLength) as TaskLength
FROM myTable
WHERE EventStartTime
BETWEEN '2019/8/17' AND '2019/8/19'
GROUP BY TaskName ORDER BY TaskLength";
using (SqlCommand cmd = new SqlCommand(query, con))
{
con.Open();
// Get a reader to loop over the results
using(SqlDataReader reader = cmd.ExecuteReader())
{
// Start reading data (until there are no more records to read)
while(reader.Read())
{
// From the current record build the TaskData info
TaskData data = new TaskData
{
Name = reader["TaskName"].ToString(),
Length = Convert.ToInt32(reader["TaskLength"]);
}
// Add this info the the collection of your results
results.Add(data);
}
}
}
}
And now, if you want to store the result to a CSV file, the code is simply
File.WriteAllLines("yourFile.csv",
string.Join(Environment.NewLine,
results.Select(x => x.Name +","+x.Length))

Can't retrieve data using ExecuteReader() when grouping queries

I need to retrieve the information stored in a database of some thousand items. If I go one by one by this way it takes a large amount of time (tac is a 8-character string):
string connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=DataBase\IMEIDB.accdb";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
using (OleDbCommand command = connection.CreateCommand())
{
OleDbDataReader reader;
command.CommandText = "SELECT TAC, Name, Model, Year, Manufacturer, LTE FROM Terminales WHERE TAC = #tac";
command.Parameters.AddWithValue("#tac", tac);
reader = command.ExecuteReader();
while (reader.Read())
{
ulong tac = Convert.ToUInt64(reader.GetString(0));
if (this.DiccionarioTerminales.ContainsKey(tac))
{
DiccionarioTerminales[tac].inDB = true;
DiccionarioTerminales[tac].Name = reader.GetValue(1).ToString();
DiccionarioTerminales[tac].Manufacturer = reader.GetValue(2).ToString();
DiccionarioTerminales[tac].Model = reader.GetValue(3).ToString();
DiccionarioTerminales[tac].Year = reader.GetValue(4).ToString();
DiccionarioTerminales[tac].LTE = reader.GetValue(5).ToString();
}
}
command.Dispose();
}
connection.Dispose();
}
It works well (I know I must use ExecuteNonQuery() if it's only one record, but this example is only a test), but if I try to group the tac 10 by 10 (now tac is a string like 'xxxxxxxx','xxxxxxxx','xxxxxxxx','xxxxxxxx'...) with the next changes in my code...
OleDbDataReader reader;
command.CommandText = "SELECT TAC, Name, Model, Year, Manufacturer, LTE FROM Terminales WHERE TAC IN (#tac)";
command.Parameters.AddWithValue("#tac", tac);
It doesn't enter in the while loop and I don't know why...
Is there something that am I missing or maybe I need to use another method to retrieve those data?
EDIT: Change the format due to the Soner Gönül answer
Because when you use this string in IN clause, it will seems like;
IN (xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx)
but the right syntax should be
IN ('xxxxxxxx','xxxxxxxx','xxxxxxxx','xxxxxxxx')
That's why it doesn't work. One solution might be, you can split your string with ,, format them with using single quotes and join them , again.
var str = "xxxxxxxx,xxxxxxxx,xxxxxxxx,xxxxxxxx";
var result = string.Join(",", str.Split(',').Select(s => string.Format("'{0}'", s)));
result will be 'xxxxxxxx','xxxxxxxx','xxxxxxxx','xxxxxxxx' and you can use it in your IN clause like;
...TAC IN (#tac)
and
command.Parameters.AddWithValue("#tac", result);
Also don't use AddWithValue as much as you can. It may generate unexpected and surprising results sometimes. Use Add method overload to specify your parameter type and it's size.
Related: Parameterize an SQL IN clause

Query with C# with a list as parameter

I'm want to refactor the following statement to change the where businessID = something to a statement where I provide a list of strings which contain all possible Ids e.g. where businessID in List. As now the query is executed in a for loop for each Id, which I'm guessing is not really performant. I can't seem to find information on how to use a List of strings as a parameter in a prepared statement.
using (SqlConnection myConnection = new SqlConnection("Data Source=.\\SERVER;Initial Catalog=DB;Integrated Security=True;TrustServerCertificate=True;User Instance=False"))
using (SqlCommand myCommand = myConnection.CreateCommand())
{
myConnection.Open();
myCommand.CommandText = "SELECT BusinessName FROM Businessess WHERE BusinessID = #Param2";
myCommand.Parameters.AddWithValue("#Param2", myParam2);
using (SqlDataReader reader = myCommand.ExecuteReader())
{
if (reader.Read())
{
string businessName = reader.GetString(reader.GetOrdinal("BusinessName"));
MessageBox.Show(businessName);
}
else
{
MessageBox.Show(string.Format("Sorry, no business found with id = {0}", myParam2));
}
}
}
You can use IN instead of equality, by adding comma separated ids in #Param2
"SELECT BusinessName FROM Businessess WHERE BusinessID IN(#Param2)";
IN
Determines whether a specified value matches any value in a subquery or a list.
As #Prescott suggested you the way to make a comma separated string from list you can have your AddWithValue like
myCommand.Parameters.AddWithValue("#Param2", String.Join(",", list));
As a side not try using stored procedure instead of inline queries, see comparison Stored procedures vs. inline SQL.
first create convert your list to comma separated string
string commaSeparatedList = yourlist.Aggregate((a, x) => a + ", " + x);
change the (=) to (In) and put the #Param between parenthesis
myCommand.CommandText = "SELECT BusinessName FROM Businessess WHERE BusinessID IN ( #Param2 )";
add the string (commaSeparatedList ) as parameter to your command
myCommand.Parameters.AddWithValue("#Param2", commaSeparatedList );

compare data from an array with numeric ID and insert it into a datagrid

I have a single array with random numbers as shown below
int[] numbers = new int[5] {2,5,3,7};
Also I have a table in my database with id and name in the ID have the same numerical values ​​to my array.
2 , Pedro
5 , Juan
3 , Claudio
7 , Gonzalo
I need to do is compare the numbers in the array with the id of the database, and if these are equal, showrange name associated in a datagrid
What thought is using a For loop on the array so,
for (int i = 0; i <numbers.length; i + +)
and show and thus obtain the names 'select value from table where id =' + numbers[i];
I need too much help, hope you can help me, thanks
Assuming you have valid connection you can use classes like SqlDataAdapter, DataTable and SqlConnection to fulfill a table with data you want. You also may use slightly different query to get results. Look at this code:
string numList = string.Join(",", numbers.Select(i=>i.ToString()).ToList());
// you need to have connection initialized with connection string
SqlDataAdapter a = new SqlDataAdapter("select value from table where id in (" + numList + ")", connection);
DataTable dt = new DataTable();// the result goes here
a.Fill(dt);// actually querying the database
That's it - you now have all your names from database which are corresponding to the list of IDs you have supplied. Now you can show that list in datagridview or datagrid.
So the question can be reduced to the ADO.NET part, how to retrieve the value from the id:
string sql = "SELECT value FROM dbo.table WHERE id = #id";
var pairs = new List<Tuple<int, string>>();
using (var con = new SqlConnection(yourConnectionString))
using (var cmd = new SqlCommand(sql, con))
{
con.Open();
foreach (int i in numbers)
{
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#id", i);
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
pairs.Add(Tuple.Create(i, dr.GetString(0)));
}
}
}
}
I have used a List<Tuple<int, string>> as collection to store all ID's and according names which you can use as datasource or further processing(i don't know if you only want to show the id's which have a name in your table). You can access the ID + name in this way:
foreach(var pair in pairs)
{
int id = pair.Item1;
string name = pair.Item2;
}
Note that i've used the using-statement to ensure that all unmanaged resources are getting disposed as soon as possible. That will also close the connection.
Always use parameters to prevent sql-injection or conversion issue even if you are currently not vulnerable to it.

How to prevent a SQL Injection escaping strings

I have some queries (to an acccess database) like this :
string comando = "SELECT * FROM ANAGRAFICA WHERE E_MAIL='" + user + "' AND PASSWORD_AZIENDA='" + password + "'";
and I'd like to "escape" user and password, preventing an injection.
How can I do it with C# and .NET 3.5? I'm searching somethings like mysql_escape_string on PHP...
You need to use parameters. Well dont have to but would be preferable.
SqlParameter[] myparm = new SqlParameter[2];
myparm[0] = new SqlParameter("#User",user);
myparm[1] = new SqlParameter("#Pass",password);
string comando = "SELECT * FROM ANAGRAFICA WHERE E_MAIL=#User AND PASSWORD_AZIENDA=#Pass";
Don't escape the strings to start with - use a parameterized query. Benefits of this over escaping:
The code is easier to read
You don't have to rely on getting the escaping correct
It's possible that there are performance improvements (DB-specific etc)
It separates "code" (the SQL) from the data, which is just good sense logically
It means you don't need to worry about data formats for things like numbers and dates/times.
The docs for SqlCommand.Parameters give a good, complete example.
You should use the SQL paramters to prevent SQL Injection
look at the code
//
// The name we are trying to match.
//
string dogName = "Fido";
//
// Use preset string for connection and open it.
//
string connectionString = ConsoleApplication716.Properties.Settings.Default.ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
//
// Description of SQL command:
// 1. It selects all cells from rows matching the name.
// 2. It uses LIKE operator because Name is a Text field.
// 3. #Name must be added as a new SqlParameter.
//
using (SqlCommand command = new SqlCommand("SELECT * FROM Dogs1 WHERE Name LIKE #Name", connection))
{
//
// Add new SqlParameter to the command.
//
command.Parameters.Add(new SqlParameter("Name", dogName));
//
// Read in the SELECT results.
//
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
int weight = reader.GetInt32(0);
string name = reader.GetString(1);
string breed = reader.GetString(2);
Console.WriteLine("Weight = {0}, Name = {1}, Breed = {2}", weight, name, breed);
}
}
}
Yes, you can avoid injection by using Named Parameters
Use parameters instead of escaping strings:
var comando = "SELECT * FROM ANAGRAFICA WHERE E_MAIL=#user AND PASSWORD_AZIENDA=#password";
Then assign values to those parameters before you execute the SqlCommand.
You can check the below link to know how to prevent SQL injection in ASP.Net. I would prefer to use
Using parametrized queries or Stored Procedures.
Validating special characters like '(very dangerous)
http://dotnet.dzone.com/news/aspnet-preventing-sql-injectio
If you can convert these to Named Parameters, I think you would be better served.
#Jethro
You could also write it like this:
SqlParameter[] sqlParams = new SqlParameter[] {
new SqlParameter("#Name", contact.name),
new SqlParameter("#Number", contact.number),
new SqlParameter("#PhotoPath", contact.photoPath),
new SqlParameter("#ID", contact.id)
};
Follow the steps below and resolve the SQL INJECTION problem:
OracleParameter[] tmpParans = new OracleParameter[1];
tmpParans[0] = new Oracle.DataAccess.Client.OracleParameter("#User", txtUser.Text);
string tmpQuery = "SELECT COD_USER, PASS FROM TB_USERS WHERE COD_USER = #User";
OracleCommand tmpComand = new OracleCommand(tmpQuery, yourConnection);
tmpComand.Parameters.AddRange(tmpParans);
OracleDataReader tmpResult = tmpComand.ExecuteReader(CommandBehavior.SingleRow);

Categories

Resources