2

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]);
            }
    }
Leon Winston
  • 141
  • 1
  • 2
  • 9
  • Is there any exception? – Szymon Mar 13 '14 at 04:52
  • 2
    Is the posted code the working code or the non-working coce? A few observations: 1. Learn parameterized queries to guard against SQL Injection. 2. If trying to open a connection throws an exception, you need to exit the method, as everything else will fail as well. 3. Use a `using` block or call `Close()` on the reader. – Tim Mar 13 '14 at 04:54
  • @Szymon yeah (There was an error parsing the query. [Token line number,Token line offset,,Token in error,,]) however when using breakpoints on the while (reader.Read()) line i found out the datareader is null. – Leon Winston Mar 13 '14 at 04:56
  • Student and lecture are both in Contact_DB table? Also check the " WHERE Student_ID" clause is right. – ray Mar 13 '14 at 04:56
  • Shouldn't the lecturer name be quoted? I.e., `SELECT * FROM Contact_DB WHERE Lecturer_Name ='" + full + "' AND Direction = '" + "To the lecturer" + "'"`? – Tim Mar 13 '14 at 05:01
  • @Tim sorry, I've now added the non working code. Also I've never learnt about sql injection so i will now research into it. 3. and sure – Leon Winston Mar 13 '14 at 05:03
  • @Tim I know you usually have to but in my working code i haven't. I tried it quoted and it produced the same results – Leon Winston Mar 13 '14 at 05:07
  • @ray Thanks your comment actually made me realize my mistake and helped me solve the problem. The database contained no results for the WHERE Student_ID – Leon Winston Mar 13 '14 at 05:13

1 Answers1

2

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

Mihai Hantea
  • 1,741
  • 13
  • 16
  • Is their anyway you could explain this in more detail please, I'm quite a novice programmer – Leon Winston Mar 13 '14 at 05:08
  • Thanks a lot, it makes sense, Sorry i cant vote up. I have low reputation. – Leon Winston Mar 13 '14 at 05:18
  • Glad to help. I update the answer with a little more details. I used .NET REFLECTOR to see how is implemented. – Mihai Hantea Mar 13 '14 at 05:22
  • @MihaiHantea - just a quick note, that the latest code has an assert for data reader != null (https://github.com/Microsoft/referencesource/blob/master/System.Data/System/Data/OleDb/OleDbCommand.cs#L658), if you want to edit that in. Cheers! – potatopeelings Mar 22 '18 at 01:00