Veamos algo más simple: Una función que devuelva cero (0) si la tabla está vacía, cero si se produce un error y el próximo ID si hay al menos un registro.
- No necesitas un DataReader, con un DataAdapter alcanza.
- No debes usar un ORDER BY, si estás consultando por MAX(), ya la función MAX() no sólo te esta devolviendo el mayor de todos, sino que además sólo devuelve un registro.
La idea es:    
Código vb:
Ver original- Private Function Obtener_ID() As Integer 
-         Try 
-             Dim cad As New MySqlConnection("Database=Pacientes;Data Source=localhost;User Id=root;Password=utan") 
-             cad.Open() 
-             Dim sql As String = "SELECT MAX(id) MaxId FROM generales;" 
-             Dim oTabla As New DataTable 
-             Dim cmd As New MySqlCommand(sql, cad) 
-             Dim oReader As New MySqlDataAdapter(cmd) 
-             oReader.Fill(oTabla) 
-             cad.Close() 
-             If oTabla.Rows.Count = 1 Then 
-                 Return Convert.ToInt32(oTabla.Rows(0).Item("MaxId")) + 1 
-             Else 
-                 Return 1 
-             End If 
-         Catch ex As MySqlException 
-             MessageBox.Show("Error:" & ex.Message) 
-             Return 0 
-         Catch ex As Exception 
-             MessageBox.Show("Error:" & ex.Message) 
-             Return 0 
-         End Try 
-     End Function 
Usar un DataReader en una operación no secuencial no tiene ningún sentido. Tiene lógica cuando vas a obtener un conjunto de registros y realizar alguna operación on-line con la tabla en forma secuencial. No es tu caso, ya que sólo quieres un dato.
De hecho, ni siquiera requieres un datatable. Alcanzaría con esto:   
Código vb:
Ver original- Private Function Obtener_ID() As Integer 
-         Try 
-             Dim Valor As Integer 
-             Dim cad As New MySqlConnection("Database=Pacientes;Data Source=localhost;User Id=root;Password=utan") 
-             cad.Open() 
-             Dim sql As String = "SELECT MAX(id) MaxId FROM generales;" 
-             Dim cmd As New MySqlCommand(sql, cad) 
-             Valor = Convert.ToInt32(cmd.ExecuteScalar) 
-             Return Valor 
-         Catch ex As MySqlException 
-             MessageBox.Show("Error:" & ex.Message) 
-             Return 0 
-         Catch ex As Exception 
-             MessageBox.Show("Error:" & ex.Message) 
-             Return 0 
-         End Try 
-     End Function 
Esto es porque ExecuteScalar() devuelve un único valor, si la consulta devuelve precisamente un sólo campo y un registro, como en este caso.