0

I have a problem with this function...

public Veiculo getVehiclebyMatricula(string MAT)
{
     Veiculo V = new Veiculo();
     SqlCommand command = new SqlCommand("select * from Veiculo where matricula =@mat;",CNManager.getConnection());
     command.Parameters.AddWithValue("@mat", MAT);
     SqlDataReader dr = command.ExecuteReader();

     if (dr.HasRows)
     {
         V._id = dr.GetInt32(0); //HERE
         V.marca = dr.GetString(1);
         V.modelo = dr.GetString(2);
         V.matricula = dr.GetString(3);
         V.estado = dr.GetString(4);
         V.preco = dr.GetInt32(5);
         V.cilindrada = dr.GetInt32(6);
         V.image = dr.GetString(7);
         V.id_tipo = dr.GetInt32(8);

         dr.Close();
         return V;
      }
      return V;
   }

the error that spawns says "Reading not valid when data is not present.."

Holger Just
  • 52,918
  • 14
  • 115
  • 123
Maverick
  • 3
  • 2

6 Answers6

3

You should really use parametrized queries and not just concatenate strings like this, because this opens doors for SQL injection. Try instead:

SqlCommand command = new SqlCommand("select * from Veiculo where matricula =@mat;",CNManager.getConnection());
command.Parameters.Add("@mat", MAT);
command.Execute...

Beside that you are closing your connection twice.

I would suggest to put your SQL connection object into a using block to make sure it's getting closed and drop your lines where you are closing your connection instead.

user3596113
  • 868
  • 14
  • 32
2

You must call dr.Read() ( SqlDataReader.Read() ) and check if it returns true before accessing your dr properties.

Perfect28
  • 11,089
  • 3
  • 25
  • 45
1

You are closing two times, dr.Close()!, the message is saying that cannot read while data not present, since you closed it, try to put in this way:

try{
 ...
 } catch(){
 } finally
 { 
     dr.Close();
 } 
Adel
  • 1,468
  • 15
  • 18
1

C# has a handy statement that closes and releases resources automatically: the using command. It does so, even if the using block is left prematurely because of an error or because of a return or break statement. You were closing the connection twice. In my example below, I use the using-statement in order to close the connection, the command and the reader.

You should not keep the connection open. This potentially consumes resources over a long time. Open it and close it (with using) each time you need a connection. The connection pool automatically keeps connections open for some time, so that the "physical" connection will not be constantly closed and reopened.

Before a record can be accessed you must move to the first (or next) record with dr.Read(). This method also returns a Boolean value telling you whether a record was there and whether the operation could be performed. Use dr.Read() instead of dr.HasRows.

I am also using a command parameter, which is both easier and safer as stitching the command together with string operations.

public Veiculo getVehiclebyMatricula(string MAT)
{
    Veiculo V = new Veiculo();
    query = "select * from Veiculo where matricula = @m";

    using (SqlConnection conn = CNManager.getConnection())
    using (var command = new SqlCommand(query, conn)) {
        command.Parameters.AddWithValue("@m", MAT);
        conn.Open();
        using (SqlDataReader dr = command.ExecuteReader()) {
            if (dr.Read()) {
                V._id = Convert.ToInt32(dr["_id"]);
                V.marca = dr["marca"].ToString();
                V.modelo = dr["modelo"].ToString();
                V.matricula = dr["matricula"].ToString();
                V.estado = Convert.ToChar(dr["estado"]);
                V.preco = Convert.ToInt32(dr["preco"]);
                V.cilindrada = Convert.ToInt32(dr["cilindrada"]);
                V.image = dr["_src"].ToString();
                V.id_tipo = Convert.ToInt32(dr["id_tipo"]);
            }
        }
    }
    return V;
}
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

As well as replacing string concatenation with SQLParameters as other answers. The return data you need to call Read() on the DataReader.

Take a look at this question for an example of accessing the resultset: Read data from SqlDataReader

Quick snippet:

using(SqlDataReader rdr = cmd.ExecuteReader())
{
    while (rdr.Read())
    {
        var myString = rdr.GetString(0); //The 0 stands for "the 0'th column", so the first column of the result.
        // Do somthing with this rows string, for example to put them in to a list
        listDeclaredElsewhere.Add(myString);
    }
}
Community
  • 1
  • 1
Chris L
  • 2,262
  • 1
  • 18
  • 33
0

I've had some problems handling SQL in C#/ASP.NET, so I always add use the Entity Framework. It is way easier to manipulate.

Here's how your problem would look with the Entity Framework...

public Veiculo getVehiclebyMatricula(string MAT)
{
    Veiculo V = new Veiculo();
    var context = new Entities(); //The name 'Entities' is up to you
    var dr = context.Veiculo.Where(m => m.matricula = MAT);
    foreach (var r in dr) {
        V._id = r._id;
        V.marca = r.marca;
        V.modelo = r.modelo;
        V.matricula = r.matricula
        V.estado = r.estado
        V.preco = r.preco;
        V.cilindrada = r.cilindrada;
        V.image = r._src
        V.id_tipo = r.id_tipo
    }
    context.Close();
}    

Lemme know if this works out for you.

Carlos Flores
  • 29
  • 2
  • 9