I'm populating my List like this:
public List<Functions> ListFunctions(int proj)
{
List<Functions> lFunctions = new List<Functions>();
try
{
string sql = "SELECT id, description FROM functios WHERE project = #project ORDER BY description ASC";
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new MySqlParameter("#project", MySqlDbType.Int32)).Value = proj;
using (MySqlDataReader reader = _dal.ExecutaReader(cmd))
{
while (reader.Read())
{
lFunctions.Add(new Function
{
ID = Convert.ToInt32(reader["id"]),
Descripton = reader["description"].ToString()
});
}
}
return lFunction;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
How may I loop through the list and get those values now ? The Description and the ID
I'd like to know a way to get exactly the fieldName, like:
string name = ListFunction["FieldName"].ToString()
You just enumerate over the returned list. For example:
var functions=ListFunctions(0); // For example
foreach(var function in functions)
{
Console.WriteLine("{0} = {1}",function.ID, function.Description);
}
Related
I am trying to get int value from the database but It is throwing an error
Unable to cast object of type 'System.Byte' to type 'System.Int32'.
In the database, Active field is tinyint.
Also, how to return both values from this method.
private string CheckData(string firstValue, string SecondValue, int Active)
{
string Data = "";
StringBuilder sb = new StringBuilder();
string query = #"select M.ident Mi, mmp.active Active
from Iden.Iden M
inner join PtM.MPt MMP on MMP.mPat = M.id
where M.ident = 'firstValue'
and Mi.ident = 'SecondValue'";
sb.Append(query);
sb.Replace("firstValue", firstValue);
sb.Replace("SecondValue", SecondValue);
SqlConnection connection = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(sb.ToString());
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
try
{
connection.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Data = reader.GetString(reader.GetOrdinal("Mi"));
Active = reader.GetInt32(reader.GetOrdinal("Active"));
}
}
}
catch (Exception ex)
{
_log.Error($"Exception:{ex.Message}");
}
finally
{
connection.Close();
connection.Dispose();
}
return Data;
}
Here's a stab at it. I can't debug it (since I don't feel like creating a database).
First I create a type to hold the results. You could just use a Tuple, but this seems clearer:
public class DataActive
{
public string Data { get; set; }
public byte Active { get; set; }
}
I make your function return a collection of these - it's not obvious from your code that there is only one.
You'll also notice that I use SqlParameters to add firstValue and secondValue to your query. Look up SQL Injection (and Little Bobby Tables).
If you are using a recent version of C# (which I don't), there's a new syntax for using that requires less indenting. The using statements stick a call to Dispose in a finally statement at the end of the block. Also note that I'm disposing the SqlCommand and the DataReader
public static IEnumerable<DataActive> CheckData(string firstValue, string secondValue)
{
var results = new List<DataActive>();
const string query = #"select M.ident Mi,mmp.active Active from Iden.Iden M
Inner join PtM.MPt MMP on MMP.mPat =M.id
where M.ident = #firstValue and Mi.ident = #secondValue";
using (var connection = new SqlConnection(connString))
{
using (var cmd = new SqlCommand(query))
{
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
cmd.Parameters.Add("#firstValue", SqlDbType.NVarChar, 50).Value = firstValue;
cmd.Parameters.Add("#secondValue", SqlDbType.NVarChar, 50).Value = secondValue;
try
{
connection.Open();
using (var reader = cmd.ExecuteReader())
{
var dataOrdinal = reader.GetOrdinal("Mi");
var activeOrdinal = reader.GetOrdinal("Active");
if (reader.HasRows)
{
while (reader.Read())
{
results.Add(new DataActive
{
Data = reader.GetString(dataOrdinal),
Active = reader.GetByte(activeOrdinal),
});
}
}
}
}
catch (Exception ex)
{
_log.Error($"Exception:{ex.Message}");
}
}
}
return results;
}
If your TINY_INT Active represents a boolean value, figure out what the rule is, and do a conversion after you get the value using reader.GetByte.
One final note, it's often better to log ex.ToString() rather than ex.Message. You get the message and the stack that way.
I want to retrive data from two differentables in my mysql data base so i created one connection and two readers, The second reader is not returning any results but the first reader is.
public List<BlogContentItemClass> BCITLIST = new List<BlogContentItemClass>();
// GET: api/BlogContents
[HttpGet]
public List<BlogContentItemClass> Get(string id)
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "SELECT * FROM test.blogtable where `id` = '" + id + "' ";
MySqlCommand cmd = new MySqlCommand(Query, conn);
MySqlDataReader MSQLRD = cmd.ExecuteReader();
BlogContentItemClass BCIT = new BlogContentItemClass();
Label BLOGID = new Label();
if (MSQLRD.HasRows)
{
while (MSQLRD.Read())
{
string TC = (MSQLRD["Topic"].ToString());
string CT = (MSQLRD["Category"].ToString());
string SM = (MSQLRD["Summary"].ToString());
string BID = (MSQLRD["id"].ToString());
BCIT.TopicSaved1 = TC;
BCIT.CategoriesSaved1 = CT;
BCIT.SummarySaved1 = SM;
BLOGID.Text = BID;
BCIT.TotalBodyStackLayout1.Add("Hello");
}
}
BCITLIST.Add(BCIT);
MSQLRD.Close();
string Query1 = "SELECT * FROM test.blogbodytable where `BlogID` = '" + BLOGID.Text + "' ";
MySqlCommand cmd1 = new MySqlCommand(Query1, conn);
MySqlDataReader MSQLRD1 = cmd1.ExecuteReader();
if (MSQLRD1.HasRows)
{
while (MSQLRD1.Read())
{
string BLOGBODY ;
BLOGBODY = (MSQLRD1["BlogBody"].ToString());
BCIT.TotalBodyStackLayout1.Add(BLOGBODY);
}
}
BCITLIST.Add(BCIT);
conn.Close();
return BCITLIST;
}
from my code the line BCIT.TotalBodyStackLayout1.Add("Hello"); in the first reader does add "hello" to the BCIT.TotalBodyStacklayout1, but the line BCIT.TotalBodyStackLayout1.Add( BLOGBODY); does not work, what am i doing wrong?
Can you be more specific what you mean by 'BCIT.TotalBodyStackLayout1.Add(BLOGBODY);' does not work. Are you getting any exception? or if BLOGBODY coming empty? There are few primitive troubleshooting steps you can perform to nail-down the issue
confirm what BLOGID.Text you are getting from your previous query and corresponding data is available in test.blogbodytable for that id.
if (MSQLRD1.HasRows) is resolving to true
Were you able to get inside while (MSQLRD1.Read())
I have a string array which consists of identifiers. I want to get some values from SQL using these identifiers . Is there a way of adding them with a string value to SqlCommand parameters?
I want to create a query like:
select CaseList from MasterReportData where Id = 1 OR Id = 2 OR Id = 3
This is my C# code:
public static List<string> GetCaseList(string[] masterIdList)
{
try
{
string query = " select CaseList from MasterReportData where #masterId";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
conn.Close();
}
catch (Exception e)
{
var err= 0;
}
return list;
}
There are many different ways you can go about doing this but I prefer to create a temp table of possible values. That way you can do something like
select CaseList from MasterReportData where Id IN(select Id from tempTable)
The best approach (with sql optimization) would be:
Create your Type:
CREATE TYPE dbo.IntTTV AS TABLE
( Id int )
Your Ids:
var ids = new List<int>
{
1,
2,
3,
}
Create a schema:
var tableSchema = new List<SqlMetaData>(1)
{
new SqlMetaData("Id", SqlDbType.Int) // I think it's Int
}.ToArray();
Create the table in C#
var table = ids
.Select(i =>
{
var row = new SqlDataRecord(tableSchema);
row.SetInt32(0, i);
return row;
})
.ToList();
Create the SQL Parameter
var parameter = new SqlParameter();
parameter.SqlDbType = SqlDbType.Structured;
parameter.ParameterName = "#Ids";
parameter.Value = table;
parameter.TypeName = "dbo.IntTTV";
var parameters = new SqlParameter[1]
{
parameter
};
Slightly change your query (this is just an example:)
string query = "select mrd.CaseList from MasterReportData mrd"
+ " inner join #ids i on mrd.Id = i.id";
public static List<string> GetCaseList(string[] masterIdList)
{
List<string> list = new List<string>();
try
{
string query = "select CaseList from MasterReportData where ";
using (SqlConnection conn = new SqlConnection(connString))
{
int i = 0;
SqlCommand cmd = new SqlCommand(query, conn);
for(i = 0; i < masterIdList.Length; i++)
{
var parm = "#ID" + i;
cmd.Parameters.Add(new SqlParameter(parm, masterIdList[i]));
query += (i > 0 ? " OR " : "") + " Id = " + parm;
}
cmd.CommandText = query;
//cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
}
}
catch (Exception e)
{
e.ToString();
}
return list;
}
With the following code I get a less-than-helpful err msg (all I can see of the err msg in the truncated title bar of the exception dialog is, "System.Data.SQLServer...")
string query = "SELECT * FROM EVERYTHING";
SqlCeCommand cmd = new SqlCeCommand(query);
SqlCeConnection conn = new SqlCeConnection(myConnStr);
conn.Open();
cmd.Connection = conn;
SqlCeDataReader myReader = cmd.ExecuteReader(CommandBehavior.CloseConnection); // <-- Blows up bigger than an Augustus Gloop pinata
UPDATE
I added this:
MessageBox.Show(string.Format("query is {0}", query));
...to do a sanity check on just what the query that was failing was, to the end that clumps of hair are now scattered all about my work area. I had this to feed the query:
string vendorId = txtVendor.ToString().Trim();
...instead of this:
string vendorId = txtVendor.Text.ToString().Trim();
...and thus the query was "SELECT BLA FROM BLA WHERE BLA = System.Windows.Forms.Label"
Now I'm at least to a "No data exists for the row/column" err msg.
I'm not sure if CF supports the CommandBehavior.CloseConnection option.
Can you write it this way?
string query = "SELECT * FROM EVERYTHING";
var table = new DataTable();
using (var cmd = new SqlCeCommand(query, new SqlCeConnection(myConnStr)); {
try {
cmd.Connection.Open();
table.Load(cmd.ExecuteReader());
} catch (SqlException err) {
Console.WriteLine(err.Message); // <= Put a Break Point here.
} finally {
cmd.Connection.Close();
}
}
object col1 = null;
string strCol2 = null;
if (0 < table.Rows.Count) {
col1 = table.Rows[0][0];
object obj = table.Rows[0][1];
if ((obj != null) && (obj != DBNull.Value)) {
strCol2 = obj.ToString();
}
}
EDIT: Added DataTable and read 2 items from Row[0].
I want to implement a simple delete button for my database. The event method looks something like this:
private void btnDeleteUser_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Are you sure?", "delete users",MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
command = new SqlCommand();
try
{
User.connection.Open();
command.Connection = User.connection;
command.CommandText = "DELETE FROM tbl_Users WHERE userID = #id";
int flag;
foreach (DataGridViewRow row in dgvUsers.SelectedRows)
{
int selectedIndex = row.Index;
int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString());
command.Parameters.AddWithValue("#id", rowUserID);
flag = command.ExecuteNonQuery();
if (flag == 1) { MessageBox.Show("Success!"); }
dgvUsers.Rows.Remove(row);
}
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
finally
{
if (ConnectionState.Open.Equals(User.connection.State))
User.connection.Close();
}
}
else
{
return;
}
}
but I get this message:
A variable #id has been declared. Variable names must be unique within
a query batch or stored procedure.
Is there any way to reuse this variable?
Parameters.AddWithValue adds a new Parameter to the command. Since you're doing that in a loop with the same name, you're getting the exception "Variable names must be unique".
So you only need one parameter, add it before the loop and change only it's value in the loop.
command.CommandText = "DELETE FROM tbl_Users WHERE userID = #id";
command.Parameters.Add("#id", SqlDbType.Int);
int flag;
foreach (DataGridViewRow row in dgvUsers.SelectedRows)
{
int selectedIndex = row.Index;
int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString());
command.Parameters["#id"].Value = rowUserID;
// ...
}
Another way is to use command.Parameters.Clear(); first. Then you can also add the parameter(s) in the loop without creating the same parameter twice.
Rather than:
command.Parameters.AddWithValue("#id", rowUserID);
Use something like:
System.Data.SqlClient.SqlParameter p = new System.Data.SqlClient.SqlParameter();
Outside the foreach, and just set manually inside the loop:
p.ParameterName = "#ID";
p.Value = rowUserID;
I would use this:
public static class DbExtensions
{
public static void AddParameter(SQLiteCommand command, string name, DbType type, object value)
{
var param = new SQLiteParameter(name, type);
param.Value = value;
command.Parameters.Add(param);
}
}
Then, call this:
DbExtensions.AddParameter(command, "#" + fieldOfSearch[i], DbType.String, value[i]);
Error is because you are adding the same parameter again and again in each iteration of the loop.
I would move that code to a seperate method so that i can call it from multiple places as needed.
public bool DeleteUser(int userId)
{
string connString = "your connectionstring";
try
{
using (var conn = new SqlConnection(connString))
{
using (var cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "DELETE FROM tbl_Users WHERE userID = #id";
cmd.Parameters.AddWithValue("#id", userId);
conn.Open();
cmd.ExecuteNonQuery();
return true;
}
}
}
catch(Exception ex)
{
//Log the Error here for Debugging
return false;
}
}
Then call it like this
foreach (DataGridViewRow row in dgvUsers.SelectedRows)
{
int selectedIndex = row.Index;
if(dgvUsers[0,selectedIndex]!=null)
{
int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString());
var result=DeleteUser(rowUserID)
}
else
{
//Not able to get the ID. Show error message to user
}
}