Update database column during the reading of rows - c#

I need to change a column value in the table of my database every time I read a row. Specifically, after the reading of the row I must set the column SENT=1 (by default, before the reading, the value is 0).
My code is:
var sqlCommand = "SELECT * FROM detector_output WHERE SENT=0";
var Command = new MySqlCommand(sqlCommand, connection);
MySqlDataReader reader = Command.ExecuteReader();
while (reader.Read())
{
var ident = reader.GetString(0);
var SENSOR_TYPE = reader.GetString(1);
var MSG_NAME = reader.GetString(2);
var DATA_NAME = reader.GetString(3);
var VALUE = reader.GetString(4);
var TIMESTAMP = reader.GetString(5);
var connectionUP = new MySqlConnection(cs);
connectionUP.Open();
var sqlCommandUPDATE = "UPDATE detector_output SET SENT=1 WHERE ID=ident";
var CommandUpdate = new MySqlCommand(sqlCommandUPDATE, connectionUP);
CommandUpdate.ExecuteReader();
The error that I have encountered is:
unknown column 'ident' in where clause ...

You don't use ident as a variable in your query. You defined it as ID=ident that's why your provider confuse and it thinks you actually try to filter where your ID column value is equal to ident column value.
What if ident is a character? Then, it would be defined as ID = 'ident', isn't it?
Define a parameter for it and later, add it's value.
var sqlCommandUPDATE = "UPDATE detector_output SET SENT=1 WHERE ID = #ident";
var CommandUpdate = new MySqlCommand(sqlCommandUPDATE, connectionUP);
CommandUpdate.Parameters.AddWithValue("#ident", ident);
Also use using statement to dispose your connections, commands and readers.

Related

C# Winform - OracleDataAdapter not persisting the records immediately

I am making changes in an old C# WinForm application.
In the code below, when the DoWork() function is invoked. It calls the two functions PerformOperation1 and PerformOperation2. Both functions have a very similar body. The only difference is that they both update different fields of the same database table.
Finally, when they both have performed their job, we fetch the records using an OracleDataAdapter.
The count of the rows returned is 0 in the code. However, if I execute the query on the database straight away, it returns some rows. This means somehow the records updated by the PerformOperation2 are not pushed to the database at the time when we call the Fill on the DataAapter.
public void DoWork()
{
PerformOperation1();
PerformOperation2();
var sql = "select * from results where result_id = 1 and is_valid = 'Y'";
var table = new DataTable();
var data = new OracleDataAdapter(new OracleCommand(sql, base.Connection));
data.Fill(table);
var count = data.Rows.Count; //It returns 0 But when execute the same query on database, it returns rows.
}
public void PerformOperation1()
{
string sql = "select seq_1, product, count_1, count_2 from results where result_id = 1";
string updateSQL = "update results set count_1 = :count_1, count_2 = :count_2 WHERE seq_1 = :seq_1";
var selectCmd = new OracleCommand(sql, base.Connection);
selectCmd.CommandType = CommandType.Text;
var adapter = new OracleDataAdapter(lCmd);
adapter.UpdateCommand = new OracleCommand(updateSQL, base.Connection);
adapter.UpdateCommand.CommandType = CommandType.Text;
AddCommandParameter(adapter.UpdateCommand, ":count_1", DbType.Double, 11, "count_1");
AddCommandParameter(adapter.UpdateCommand, ":count_2", DbType.Double, 11, "count_2");
var data = new DataSet();
adapter.Fill(data);
foreach (var row in data.Tables[0].Rows)
{
row["count_1"] = GetCount1(row["seq1"]); //Returns Count1
row["count_2"] = GetCount2(row["seq1"]); //Returns Count2
//Forces an immediate garbage collection of all generations
GC.Collect();
GC.WaitForPendingFinalizers();
}
adapter.Update(data);
data.AcceptChanges();
}
public void PerformOperation2()
{
string sql = "select seq_1, product, is_valid from results where result_id = 1";
string updateSQL = "update results set is_valid = :is_valid WHERE seq_1 = :seq_1";
//Does exactly the samething like PerformOperation1 function above.
//100% same code.
//Only difference is that it updates different column named is_valid (with value 'Y' or 'N')
}
public void AddCommandParameter(DbCommand aoCommand, string asParamName, DbType aoDataType, int aiSize, string asColName)
{
if (aoCommand is OracleCommand)
{
OracleCommand loCommand = (OracleCommand)aoCommand;
OracleType loOraDataType = ConvertToOracleType(aoDataType);
loCommand.Parameters.Add(asParamName, loOraDataType, aiSize, asColName);
}
}
Any idea why this is happening, please?
I figured it out. It was not a coding issue. It was some underlying database view problem.

How to return a data from while c# using oracle 11g

I need to return all values from my table. How to write a code inside while?
var stringConnection = "Data Source = X; User Id = X; Password = X";
var sql = "SELECT * FROM TABLE";
OracleConnection _oracleConnection = new OracleConnection(stringConnection);
_oracleConnection.Open();
OracleCommand cmd = new OracleCommand(sql, _oracleConnection);
var dr = cmd.ExecuteReader();
var list = new List<dynamic>();
while(dr.Read())
{
// my doubt is here
}
return list;
var stringConnection = "Data Source = X; User Id = X; Password = X";
var sql = "SELECT * FROM TABLE";
OracleConnection _oracleConnection = new OracleConnection(stringConnection);
_oracleConnection.Open();
OracleCommand cmd = new OracleCommand(sql, _oracleConnection);
var dr = cmd.ExecuteReader();
var list = new List<dynamic>();
while(dr.Read())
{
// **** read column name data from table ****
string Id = (string)dr["Id"];
string company = (string)dr["company"];
string city = (string)dr["City"];
var objItem = new { Id = Id, company = company, city = "city" };
list.Add(objItem);
}
return list;
You have several options. 1 - load DataSet from OracleDataReader. There you will have all your data.
2 - you can still use select *... but you need a model. Then create List<SomeModel> instead of List<dynamic> with
while (reader.Read())
{
model.Property = reader["columnName"]; // will need convert type and take care of DB null. Can use existing extnsions
. . . .
}
3 - For arbitrary number of columns use OracleDataReader.FieldCount and some storage like List<object[]>
var data = new List<object[]>();
var fCnt = reader.FieldCount;
while (reader.Read())
{
var arr = new Object[fCnt];
for(int i = 0; i < fCnt; i++)
arr[i] = reader[i];
data.Add(arr);
}
The unfortunate part with #3 is that in the end you can get jagged array and not 2-dimentional one but you now have enough info to convert it. But I don't remember when I needed to do #3. So think about #1 and #2
And one more thing - absolutely no need for dynamic here. Stay away.

C# SQLite3 Select if null

I want the code to do something if the thing its looking for doesn't exist in the DB. This is what I am working with currently:
const string cs = #"Data Source= ..\..\..\database.sqlite3";
await using var con = new SQLiteConnection(cs);
con.Open();
await using var cmd = new SQLiteCommand(con);
member ??= ctx.Member;
cmd.CommandText = #"SELECT iq FROM users WHERE id = $user_id";
cmd.Parameters.AddWithValue("$user_id", member.Id);
var r = cmd.ExecuteReader();
while (r.Read())
{
if (r["iq"] == null)
{
var random = new Random();
var iq = random.Next(1, 200);
await cmd.DisposeAsync();
cmd.CommandText = "INSERT INTO users(id, iq) VALUES($member_id, $id)";
cmd.Parameters.AddWithValue("$iq", iq);
cmd.Parameters.AddWithValue("$member_id", member.Id);
cmd.ExecuteNonQuery();
var embed = new DiscordEmbedBuilder
{
Title = $"IQ of {member.Username} is {iq} :brain:",
Color = DiscordColor.Cyan
};
await ctx.Channel.SendMessageAsync(embed);
}
else
{
var iqFinal = r["iq"];
var embed = new DiscordEmbedBuilder
{
Title = $"IQ of {member.Username} is {iqFinal} :brain:",
Color = DiscordColor.Cyan
};
await ctx.Channel.SendMessageAsync(embed);
}
}
I really don't know how do make that happen, I've tried try catch blocks but they didn't seem to work either. How can I do this?
I assume that id is the primary key of the table, so you don't expect more than 1 rows from the statement:
SELECT iq FROM users WHERE id = $user_id
The problem with this statement is that it may not return any rows if $user_id does not exist in the table, so in this case r.Read() will return false and the code inside the while loop will never be executed.
One way to do what you want is to use aggregation:
SELECT MAX(iq) AS iq FROM users WHERE id = $user_id
which always returns a row: either the row with the iq where id = $user_id or null if $user_id does not exist in the table.
Also you should change the while loop to just:
if (r.Read()) {
.....................
}
or better just:
r.Read();
because the aggregation query is guaranteed that will return exactly 1 row.

Read Entity objects from database using EntityDataReader

Due to some reason I need to read entity objects directly from database using ADO.Net.
I've found below snippet from Microsoft documentation. I want to know are there any methods to read whole row into an Onject ('contact' in this sample) using EntityDataReader instead of mapping every single field to every property? I mean instead of reading Contact.Id and Contact.Name and other fields one by one, are there any methods which read one row into one object or not?
using (EntityConnection conn =
new EntityConnection("name=AdventureWorksEntities"))
{
conn.Open();
string esqlQuery = #"SELECT VALUE contacts FROM
AdventureWorksEntities.Contacts AS contacts
WHERE contacts.ContactID == #id";
// Create an EntityCommand.
using (EntityCommand cmd = conn.CreateCommand())
{
cmd.CommandText = esqlQuery;
EntityParameter param = new EntityParameter();
param.ParameterName = "id";
param.Value = 3;
cmd.Parameters.Add(param);
// Execute the command.
using (EntityDataReader rdr =
cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
// The result returned by this query contains
// Address complex Types.
while (rdr.Read())
{
// Display CustomerID
Console.WriteLine("Contact ID: {0}",
rdr["ContactID"]);
// Display Address information.
DbDataRecord nestedRecord =
rdr["EmailPhoneComplexProperty"] as DbDataRecord;
Console.WriteLine("Email and Phone Info:");
for (int i = 0; i < nestedRecord.FieldCount; i++)
{
Console.WriteLine(" " + nestedRecord.GetName(i) +
": " + nestedRecord.GetValue(i));
}
}
}
}
conn.Close();
}
Your cleanest option is to use execute your query using EntityFramework as suggested by #herosuper
In your example, you'd need to do something like this:
EntityContext ctx = new EntityContext();
var contacts= ctx.Contacts
.SqlQuery("SELECT * FROM AdventureWorksEntities.Contacts AS contacts"
+ "WHERE contacts.ContactID =#id", new SqlParameter("#id", 3)).ToList();
From here, you would be able to:
var myvariable = contacts[0].ContactID;//zero is index of list. you can use foreach loop.
var mysecondvariable = contacts[0].EmailPhoneComplexProperty;
Alternatively, you might skip the whole SQL string by by doing this:
EntityContext ctx = new EntityContext();
var contact= ctx.Contacts.Where(a=> a.ContactID ==3).ToList();
I'm assuming the query returns more than one record, otherwise you would just use FirstOrDefault() instead of Where()

connect and read .MDB item with C#

Is it possible to connect to a local MDB file and pick a single bit of info out of it ?
I have a table in a .mbd file with a single bit of info in it. I would like to have that record be output into a disabled textbox for a reference. I believe I can get the DB open, and run the query but no idea what I need to read from it.
thanks
var myDataTable = new DataTable();
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var adapter = new OleDbDataAdapter(query, conection);
OleDbCommandBuilder oleDbCommandBuilder = new OleDbCommandBuilder(adapter);
}
To simply read a single field on your database table you could use an OleDbDataReader that could loop over the result and return the field required..
var myDataTable = new DataTable();
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var command = new OleDbCommand(query, conection);
var reader = command.ExecuteReader();
while(reader.Read())
textBox1.Text = reader[0].ToString();
}
if you have just one record and just one field then a better solution is the method ExecuteScalar
conection.Open();
// A query that returns just one record composed of just one field
var query = "Select siteid From n_user where userid=1";
var command = new OleDbCommand(query, conection);
int result = (int)command.ExecuteScalar(); // Supposing that siteid is an integer
Probably I should also mention that ExecuteScalar returns null if the query doesn't find a match for the userid, so it is better to be careful with the conversion here
object result = command.ExecuteScalar();
if( result != null)
int userID = (int)result;
.....
Yes very possible. Just have the adapter fill the DataTable, also I don't think you'll need the OleDbCommandBuilder.
using (var conection = new OleDbConnection("Provider=Microsoft.JET.OLEDB.4.0;" + "data source=C:\\menus\\newmenus\\menu.mdb;Password=****"))
{
conection.Open();
var query = "Select siteid From n_user";
var adapter = new OleDbDataAdapter(query, conection);
adapter.Fill(myDataTable);
myTextBox.Text = myDataTable.Rows[0][0].ToString();
}
Also I think using ExecuteScalar would be a better solution, but my answer was tailored to the objects you had already instantiated.
You could use OleDbCommand.ExecuteScalar to retrieve a single value. It is returned as an object and you could cast it to the correct type.
Are you looking for stm like this?
OleDbCommand cmd = new OleDbCommand();
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
// read ur stuff here.
}

Categories