I'm currently building a program which stores messages between users in a database and returns these messages to the user when the button below gets pressed. I'm using a SQL CE database using a OleDbConnection and using a DataReader.
private void button3_Click(object sender, EventArgs e)
{
string [] lec_name = new string [10] ;
string [] content = new string [10] ;
string conn = "Provider=Microsoft.SQLSERVER.CE.OLEDB.3.5;Data Source=C:\\Users\\Leon\\Admin.sdf";
OleDbConnection connection = new OleDbConnection(conn);
OleDbCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM Contact_DB WHERE Student_ID =" + iD + " AND Direction = '" + "To the student" + "'";
try
{
connection.Open();
}
catch (Exception ex)
{
MessageBox.Show("" + ex.Message);
}
OleDbDataReader reader = command.ExecuteReader();
int up = 0;
int count = 0;
while (reader.Read())
{
lec_name[up] = reader["Lecturer_Name"].ToString();
content[up] = reader["Description"].ToString();
up++;
MessageBox.Show("The lecturer " + lec_name[count] + " has messaged you saying :" + "\n" + content[count]);
count++;
}
}
This code works for my Student class but when I reuse the code with minor changes within the Lecturer class the OledbDataReader says null, anyone know why?
Btw the values being returned aren't null the reader itself is null.
Below is the non working code.
private void button2_Click(object sender, EventArgs e)
{
string [] studentID = new string [10] ;
string [] content = new string [10] ;
string conn = "Provider=Microsoft.SQLSERVER.CE.OLEDB.3.5;Data Source=C:\\Users\\Leon\\Admin.sdf";
OleDbConnection connection = new OleDbConnection(conn);
OleDbCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM Contact_DB WHERE Lecturer_Name =" + full + " AND Direction = '" + "To the lecturer" + "'";
try
{
connection.Open();
}
catch (Exception ex)
{
MessageBox.Show("" + ex.Message);
}
OleDbDataReader reader1 = command.ExecuteReader();
int up = 0;
int count = 0;
while (reader1.Read())
{
studentID[up] = reader1["Student_ID"].ToString();
content[up] = reader1["Description"].ToString();
up++;
}
MessageBox.Show("The student " + studentID[count] + " has messaged you saying :" + "\n" +content[count]);
}
}
Using Reflector:
OleDbCommand.ExcuteReader:
public OleDbDataReader ExecuteReader(CommandBehavior behavior)
{
OleDbDataReader reader;
IntPtr ptr;
OleDbConnection.ExecutePermission.Demand();
Bid.ScopeEnter(out ptr, "<oledb.OleDbCommand.ExecuteReader|API> %d#, behavior=%d{ds.CommandBehavior}\n", this.ObjectID, (int) behavior);
try
{
this._executeQuery = true;
reader = this.ExecuteReaderInternal(behavior, "ExecuteReader");
}
finally
{
Bid.ScopeLeave(ref ptr);
}
return reader;
}
The CommandBehavior is
default.the reader returned by this.ExecuteReaderInternal()---- >
private OleDbDataReader ExecuteReaderInternal(CommandBehavior behavior, string method)
{
OleDbDataReader dataReader = null;
OleDbException previous = null;
int num2 = 0;
try
{
object obj2;
int num;
this.ValidateConnectionAndTransaction(method);
if ((CommandBehavior.SingleRow & behavior) != CommandBehavior.Default) behavior |= CommandBehavior.SingleResult;
switch (this.CommandType)
{
case ((CommandType) 0):
case CommandType.Text:
case CommandType.StoredProcedure:
num = this.ExecuteCommand(behavior, out obj2);
break;
case CommandType.TableDirect:
num = this.ExecuteTableDirect(behavior, out obj2);
break;
default:
throw ADP.InvalidCommandType(this.CommandType);
}
if (this._executeQuery)
{
try
{
dataReader = new OleDbDataReader(this._connection, this, 0, this.commandBehavior);
switch (num)
{
case 0:
dataReader.InitializeIMultipleResults(obj2);
dataReader.NextResult();
break;
case 1:
dataReader.InitializeIRowset(obj2, ChapterHandle.DB_NULL_HCHAPTER, this._recordsAffected);
dataReader.BuildMetaInfo();
dataReader.HasRowsRead();
break;
case 2:
dataReader.InitializeIRow(obj2, this._recordsAffected);
dataReader.BuildMetaInfo();
break;
case 3:
if (!this._isPrepared) this.PrepareCommandText(2);
OleDbDataReader.GenerateSchemaTable(dataReader, this._icommandText, behavior);
break;
}
obj2 = null;
this._hasDataReader = true;
this._connection.AddWeakReference(dataReader, 2);
num2 = 1;
return dataReader;
}
finally
{
if (1 != num2)
{
this.canceling = true;
if (dataReader != null)
{
dataReader.Dispose();
dataReader = null;
}
}
}
}
try
{
if (num == 0)
{
UnsafeNativeMethods.IMultipleResults imultipleResults = (UnsafeNativeMethods.IMultipleResults) obj2;
previous = OleDbDataReader.NextResults(imultipleResults, this._connection, this, out this._recordsAffected);
}
}
finally
{
try
{
if (obj2 != null)
{
Marshal.ReleaseComObject(obj2);
obj2 = null;
}
this.CloseFromDataReader(this.ParameterBindings);
}
catch (Exception exception3)
{
if (!ADP.IsCatchableExceptionType(exception3)) throw;
if (previous == null) throw;
previous = new OleDbException(previous, exception3);
}
}
}
finally
{
try
{
if (dataReader == null && 1 != num2) this.ParameterCleanup();
}
catch (Exception exception2)
{
if (!ADP.IsCatchableExceptionType(exception2)) throw;
if (previous == null) throw;
previous = new OleDbException(previous, exception2);
}
if (previous != null) throw previous;
}
return dataReader;
}
this._executeQuery wraps the new instance of OleDbDataReader, if it doesn't run the dataReader will be null.
The only way the reader is returned as null is if the internal RunExecuteReader method is passed 'false' for returnStream, which it isn't.
Here is the only place where this._executeQuery is set to false, but this one is not called in parallel because of Bid.ScopeEnter and Bid.ScopeLeave.
public override int ExecuteNonQuery()
{
int num;
IntPtr ptr;
OleDbConnection.ExecutePermission.Demand();
Bid.ScopeEnter(out ptr, "<oledb.OleDbCommand.ExecuteNonQuery|API> %d#\n", this.ObjectID);
try
{
this._executeQuery = false;
this.ExecuteReaderInternal(CommandBehavior.Default, "ExecuteNonQuery");
num = ADP.IntPtrToInt32(this._recordsAffected);
}
finally
{
Bid.ScopeLeave(ref ptr);
}
return num;
}
Theoretically the data reader can be null if the query cannot be executed.
UPDATE:
https://github.com/Microsoft/referencesource/blob/master/System.Data/System/Data/OleDb/OleDbCommand.cs#L658
Related
I am attempting to create a database access layer. I am looking for some improvements to this class/recommendations on best practice. It would be helpful if someone could point me to documentation on how this could be potentially done/things to consider. I have looked at using entity framework but it does not seem applicable, however, should I really be looking to move to EF? Is ADO.NET an outdated way of doing this?
public static IDbCommand GetCommandObject(string Connstring)
{
IDbConnection conn = new SqlConnection(Connstring);
return new SqlCommand { Connection = (SqlConnection)conn };
}
public static void AddParameter(ref IDbCommand cmd, string Name, object value, DbType ParamType)
{
IDbDataParameter Param = cmd.CreateParameter();
Param.DbType = ParamType;
Param.ParameterName = (Name.StartsWith("#")) ? "" : "#"; //# character for MS SQL database
Param.Value = value;
cmd.Parameters.Add(Param);
}
public static Int32 ExecuteNonQuery(string SQL, IDbCommand cmd = null)
{
Boolean CommitTrans = true;
Boolean CloseConn = true;
SqlTransaction Trans = null;
try
{
//IF Required - create command object if required
if (cmd == null) { cmd = DB.GetCommandObject(""); }
//Add the commandtext
cmd.CommandText = SQL;
if (cmd.Connection == null) { throw new Exception("No connection set"); }
//IF REQUIRED - open the connection
if (cmd.Connection.State == ConnectionState.Closed)
{
cmd.Connection.Open();
}
else
{
CloseConn = false;
}
if (cmd.Transaction != null)
{
//We have already been passed a Transaction so dont close it
CommitTrans = false;
}
else
{
//Create and open a new transaction
Trans = (SqlTransaction)cmd.Connection.BeginTransaction();
cmd.Transaction = Trans;
}
Int32 rtn = cmd.ExecuteNonQuery();
if (CommitTrans == true) { Trans.Commit(); }
return rtn;
}
catch (Exception e)
{
if (CommitTrans == true) { Trans.Rollback(); }
throw new Exception();
}
finally
{
if (CloseConn == true)
{
cmd.Connection.Close();
cmd = null;
}
}
}
public static object ExecuteScalar(string SQL, IDbCommand cmd, Boolean NeedsTransaction = true)
{
Boolean CommitTrans = true;
Boolean CloseConn = true;
SqlTransaction Trans = null;
try
{
//IF Required - create command object if required
if (cmd == null) { cmd = DB.GetCommandObject(""); }
//Add the commandtext
cmd.CommandText = SQL;
//IF REQUIRED - create default Connection to CourseBuilder DB
if (cmd.Connection == null) { throw new Exception("No Connection Object"); }
//IF REQUIRED - open the connection
if (cmd.Connection.State == ConnectionState.Closed)
{
cmd.Connection.Open();
}
else
{
CloseConn = false;
}
if (NeedsTransaction == true)
{
if (cmd.Transaction != null)
{
//We have already been passed a Transaction so dont close it
CommitTrans = false;
}
else
{
//Create and open a new transaction
Trans = (SqlTransaction)cmd.Connection.BeginTransaction();
cmd.Transaction = Trans;
}
}
Object rtn = cmd.ExecuteScalar();
if (NeedsTransaction == true && CommitTrans == true) { Trans.Commit(); }
return rtn;
}
catch
{
if (NeedsTransaction == true && Trans != null) { Trans.Rollback(); }
throw new Exception();
}
finally
{
if (CloseConn == true) { cmd.Connection.Close(); cmd = null; }
}
}
public static DataRow GetDataRow(string SQL, IDbCommand cmd = null, Boolean ErrorOnEmpty = true)
{
var dt = FillDatatable(SQL, ref cmd);
if (dt.Rows.Count > 0)
{
return dt.Rows[0];
}
else
{
if (ErrorOnEmpty == true) { throw new Exception(nameof(GetDataRow) + " returned no rows."); }
return null;
}
}
public static DataTable FillDatatable(string SQL, ref IDbCommand cmd)
{
string newline = System.Environment.NewLine;
var DT = new DataTable();
Boolean LeaveConOpen = false;
try
{
//Add the commandtext
cmd.CommandText = SQL;
//IF REQUIRED - create default Connection to CourseBuilder DB
if (cmd?.Connection == null) { throw new Exception("No Connection Object"); }
if (cmd.Connection.State != ConnectionState.Open)
{
cmd.Connection.Open();
LeaveConOpen = false;
}
else
{
LeaveConOpen = true;
}
var DA = new SqlDataAdapter((SqlCommand)cmd);
DA.Fill(DT);
}
catch (Exception ex)
{
var sbErr = new StringBuilder();
sbErr.AppendLine("Parameters (type defaults to varchar(max)):" + newline);
foreach (SqlParameter p in cmd.Parameters)
{
string s = "";
sbErr.AppendLine("declare " + p.ParameterName + " varchar(max) = '" + (p.Value == DBNull.Value ? "Null" : p.Value + "'; ") + newline);
}
sbErr.AppendLine(newline + SQL + newline);
throw new Exception("Failed to FillDataTable:" + newline + newline + sbErr.ToString(), ex);
}
finally
{
if (LeaveConOpen == false) { cmd.Connection.Close(); }
}
return DT;
}
public static T CheckNull<T>(T value, T DefaultValue)
{
if (value == null || value is System.DBNull)
{
return DefaultValue;
}
else
{
return value;
}
}
Couple of things to keep in mind when you are creating a DAL
DAL should be able to cater to multiple Databases (oracle , sql , mysql etc..)
You should have minimum of DB , Connection , Command and Reader implementations of each.
Do not worry about the connection pool
Be aware of the transaction scope , Especially when you are trying to save nested objects. (For Eg: by saving company, you are saving Company and Company.Employees and Employee.Phones in a single transaction)
Alternative is to use something like Dapper.
enter image description here
I have bit of code in my program that will not let and operator start another batch until they finish the one that they are on but still allows another operator to start the same batch. The sqldatareader is returning the correct data i.e. 17080387-002 but the program keeps going to the "Please finish batch" step. I'm trying to figure out if it possibly has anything to do with how the batch is being returned.
public void BatchLockOut()
{
string eventID = null;
string batchLock = null;
string enteredLot = TextBoxLot.Text;
string connectionString = "";
string commandText = "SELECT BadgeNo, Container_ID, Event_ID, Event_Time " +
"FROM dbo.Custom_EventLog " +
"WHERE Event_Time IN (SELECT MAX(Event_Time) FROM dbo.Custom_EventLog WHERE BadgeNo = #BADGENO)";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.Parameters.Add("#BADGENO", SqlDbType.NChar, 10).Value = TextBoxLogin.Text;
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
eventID = Convert.ToInt32(reader["Event_ID"]).ToString();
batchLock = reader["Container_ID"] as string;
break;
}
}
connection.Close();
}
if (batchLock == null)
{
ButtonBeginStir.IsEnabled = true;
}
else if (batchLock != enteredLot)
{
if (eventID == "1")
{
MessageBox.Show("Please finish previous stir", "Finish Stir", MessageBoxButton.OK, MessageBoxImage.Information);
ClearForm();
}
else
{
ButtonBeginStir.IsEnabled = true;
}
}
else if (batchLock == enteredLot)
{
if (eventID == "1")
{
ButtonEndStir.IsEnabled = true;
}
else if (eventID == "2")
{
ButtonBeginStir.IsEnabled = true;
}
}
}
I'm using SQLite with C#.
I use the following method to loop through a list of tv shows and their episodes and insert them into the database. It ends up entering about 1200 rows and takes 2 minutes 28 seconds. It feels like that's kinda slow so I would like people to look over my method and see if i'm doing something stupid (I'm sorta new to this).
public void InsertAllEpisodes(List<TVDBSharp.Models.Show> showList)
{
using (SQLiteConnection dbconnection = new SQLiteConnection(connectionString))
{
string seasonNumber;
string episodeNumber;
string insertShowSQL = #"INSERT INTO AllEpisodes (Key, ShowName, ShowId, EpisodeName, SeasonEpisode) VALUES (#Key, #ShowName, #ShowId, #EpisodeName, #SeasonEpisode)";
foreach (var show in showList)
{
foreach (var episode in show.Episodes)
{
if (episode.SeasonNumber != 0)
{
string seasonEpisode = "default";
if ((episode.SeasonNumber != 0) && (episode.SeasonNumber.ToString().Length == 1)) { seasonNumber = "0" + episode.SeasonNumber.ToString(); }
else { seasonNumber = episode.SeasonNumber.ToString(); }
if (episode.EpisodeNumber.ToString().Length == 1) { episodeNumber = "0" + episode.EpisodeNumber.ToString(); }
else { episodeNumber = episode.EpisodeNumber.ToString(); }
seasonEpisode = seasonNumber + episodeNumber;
SQLiteCommand command = new SQLiteCommand(insertShowSQL, dbconnection);
command.Parameters.AddWithValue("Key", show.Id + seasonEpisode);
command.Parameters.AddWithValue("ShowName", show.Name);
command.Parameters.AddWithValue("ShowId", show.Id);
command.Parameters.AddWithValue("EpisodeName", episode.Title);
command.Parameters.AddWithValue("SeasonEpisode", seasonEpisode);
dbconnection.Open();
try
{
command.ExecuteScalar();
}
catch (SQLiteException ex)
{
if (ex.ResultCode != SQLiteErrorCode.Constraint)
{
File.AppendAllText(programDataPath + "SQLErrors.txt", ex.Message + "\n");
}
}
dbconnection.Close();
}
}
}
}
}
I read up on and used sqlComm = new SQLiteCommand("begin", dbconnection) and sqlComm = new SQLiteCommand("end", dbconnection) and it inserted it in less than 1 second.
public void InsertAllEpisodes(List<TVDBSharp.Models.Show> showList)
{
using (SQLiteConnection dbconnection = new SQLiteConnection(connectionString))
{
dbconnection.Open();
string seasonNumber;
string episodeNumber;
string insertShowSQL = #"INSERT INTO AllEpisodes (Key, ShowName, ShowId, EpisodeName, SeasonEpisode) VALUES (#Key, #ShowName, #ShowId, #EpisodeName, #SeasonEpisode)";
SQLiteCommand sqlComm;
sqlComm = new SQLiteCommand("begin", dbconnection);
sqlComm.ExecuteNonQuery();
foreach (var show in showList)
{
foreach (var episode in show.Episodes)
{
if (episode.SeasonNumber != 0)
{
string seasonEpisode = "default";
if ((episode.SeasonNumber != 0) && (episode.SeasonNumber.ToString().Length == 1)) { seasonNumber = "0" + episode.SeasonNumber.ToString(); }
else { seasonNumber = episode.SeasonNumber.ToString(); }
if (episode.EpisodeNumber.ToString().Length == 1) { episodeNumber = "0" + episode.EpisodeNumber.ToString(); }
else { episodeNumber = episode.EpisodeNumber.ToString(); }
seasonEpisode = seasonNumber + episodeNumber;
sqlComm = new SQLiteCommand(insertShowSQL, dbconnection);
sqlComm.Parameters.AddWithValue("Key", show.Id + seasonEpisode);
sqlComm.Parameters.AddWithValue("ShowName", show.Name);
sqlComm.Parameters.AddWithValue("ShowId", show.Id);
sqlComm.Parameters.AddWithValue("EpisodeName", episode.Title);
sqlComm.Parameters.AddWithValue("SeasonEpisode", seasonEpisode);
try
{
sqlComm.ExecuteScalar();
}
catch (SQLiteException ex)
{
if (ex.ResultCode != SQLiteErrorCode.Constraint)
{
File.AppendAllText(programDataPath + "SQLErrors.txt", ex.Message + "\n");
}
}
}
}
}
sqlComm = new SQLiteCommand("end", dbconnection);
sqlComm.ExecuteNonQuery();
dbconnection.Close();
}
}
I have the following code in PowerBuilder (with Oracle as the DB)
DECLARE lcur_pat_q CURSOR FOR
SELECT HL7_MSG
FROM HL7_EXPORT_MSG_Q
WHERE SOCKET_NUM = :al_socket_num
AND (:as_export_level = 'C' OR ACCOUNT_NUM = :gv_acctnum)
AND SUBSTR(HL7_MSG_TYPE, 1, 3) = 'ADT'
ORDER BY HL7_EXPORT_MSG_Q_NUM
FOR UPDATE OF HL7_EXPORT_MSG_Q_NUM;
OPEN lcur_pat_q;
How can I rewrite this cursor in C#?
This variant
var dbCmd_lcur_pat_q = new OracleCommand();
dbCmd_lcur_pat_q.CommandText = "SELECT HL7_MSG, HL7_EXPORT_MSG_Q_NUM " +
" FROM HL7_EXPORT_MSG_Q " +
" WHERE SOCKET_NUM = :al_socket_num " +
" AND (:as_export_level = 'C' OR ACCOUNT_NUM = :gv_acctnum) " +
" AND SUBSTR(HL7_MSG_TYPE, 1, 3) = 'ADT' " +
"ORDER BY HL7_EXPORT_MSG_Q_NUM";
dbCmd_lcur_pat_q.Parameters.Add("al_socket_num", OracleDbType.Int32);
dbCmd_lcur_pat_q.Parameters["al_socket_num"].Value = al_socket_num ?? (object)DBNull.Value;
dbCmd_lcur_pat_q.Parameters.Add("as_export_level", OracleDbType.NVarchar2);
dbCmd_lcur_pat_q.Parameters["as_export_level"].Value = as_export_level ?? (object)DBNull.Value;
dbCmd_lcur_pat_q.Parameters.Add("gv_acctnum", OracleDbType.Int32);
dbCmd_lcur_pat_q.Parameters["gv_acctnum"].Value = AppGlobalVariables.gv_acctnum ?? (object)DBNull.Value;
dbCmd_lcur_pat_q.CommandType = CommandType.Text;
var lcur_pat_q = AppGlobalVariables.sqlca.ExecuteReader(dbCmd_lcur_pat_q);
returns empty variable lcur_pat_q
The code of ExecuteReader:
public OracleDataReader ExecuteReader(OracleCommand command)
{
try
{
if (_connection == null)
_connection = InitializeConnection();
if (_transaction == null)
_transaction = _connection.BeginTransaction();
command.Connection = _connection;
command.Transaction = _transaction;
sqlcode = 0;
sqlerrtext = String.Empty;
command.CommandTimeout = 30;
command.BindByName = true;
var reader = command.ExecuteReader();
if (reader == null) return null;
if (!reader.HasRows)
sqlcode = 100;
return reader;
}
catch (OracleException e)
{
sqlcode = e.ErrorCode;
sqlerrtext = e.Message;
Debug.Print("{0}: {1}", sqlcode, sqlerrtext);
return null;
}
catch (Exception e)
{
sqlcode = -999;
sqlerrtext = e.Message;
Debug.Print("{0}: {1}", sqlcode, sqlerrtext);
return null;
}
}
I have no idea how to do this and need help.
Can somebody help understand this code?
protected void Page_Load(object sender, EventArgs e)
{
Database database = new Database();
OleDbConnection conn = database.connectDatabase();
if (Request.Cookies["BesteldeArtikelen"] == null)
{
lbl_leeg.Text = "Er zijn nog geen bestelde artikelen";
}
else
{
HttpCookie best = Request.Cookies["BesteldeArtikelen"];
int aantal_bestel = best.Values.AllKeys.Length;
int[] bestelde = new int[aantal_bestel];
int index = 0;
foreach (string art_id in best.Values.AllKeys)
{
int aantalbesteld = int.Parse(aantalVoorArtikel(int.Parse(art_id)));
int artikel_id = int.Parse(art_id); // moet getalletje zijn
if (aantalbesteld != 0)
{
bestelde[index] = artikel_id;
}
index++;
}
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT artikel_id, naam, prijs, vegetarische FROM artikel WHERE artikel_id IN (" +
String.Join(", ", bestelde) + ")";
try
{
conn.Open();
OleDbDataReader reader = cmd.ExecuteReader();
GridView1.DataSource = reader;
GridView1.DataBind();
}
catch (Exception error)
{
errorMessage.Text = error.ToString();
}
finally
{
conn.Close();
}
}
}
And there is this part of code i dont really understand:
public string aantalVoorArtikel(object id)
{
int artikel_id = (int)id;
if (Request.Cookies["BesteldeArtikelen"] != null &&
Request.Cookies["BesteldeArtikelen"][artikel_id.ToString()] != null)
{
return Request.Cookies["BesteldeArtikelen"][artikel_id.ToString()];
}
else
{
return "0";
}
}
It extracts values from a cookie and builds an int array. (Displays a message if the cookie value is null) The int array is then used as the value for the SQL IN operator when querying the database. The result set is then bound to the GridView.