SQL Server错误-丢失数据

本文关键字:数据 Server 错误 SQL | 更新日期: 2023-09-27 18:04:09

我有一个问题,这个函数…

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;
   }

生成的错误说"当数据不存在时读取无效…"

SQL Server错误-丢失数据

您应该真正使用参数化查询,而不仅仅是像这样连接字符串,因为这为SQL注入打开了大门。试试相反:

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

除此之外,您还关闭了两次连接。

我建议把你的SQL连接对象到一个using块,以确保它正在关闭,并放弃你的行,你正在关闭你的连接,而不是

在访问dr属性之前,必须调用dr.Read() (SqlDataReader.Read())并检查它是否返回true。

c#有一个方便的语句可以自动关闭和释放资源:using命令。即使using块由于错误或returnbreak语句而过早地离开,它也会这样做。你关闭了两次连接。在下面的示例中,我使用using -语句来关闭连接、命令和读取器。

你不应该保持连接打开。这可能会在很长一段时间内消耗资源。每次需要连接时打开并关闭它(使用using)。连接池自动保持连接打开一段时间,这样"物理"连接就不会经常关闭和重新打开。

在可以访问记录之前,必须使用dr.Read()移动到第一条(或下一条)记录。该方法还返回一个布尔值,告诉您是否有记录以及是否可以执行操作。使用dr.Read()代替dr.HasRows

我还使用了命令参数,将命令与字符串操作拼接在一起既容易又安全。

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;
}

您关闭了两次,dr.Close()!,消息说,不能读取,而数据不存在,因为你关闭它,试着这样做:

try{
 ...
 } catch(){
 } finally
 { 
     dr.Close();
 } 

以及将字符串连接替换为SQLParameters作为其他答案。返回的数据需要在DataReader上调用Read()

看一下这个问题,看一个访问结果集的例子:

快速代码片段:

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);
    }
}

我在c#/ASP中处理SQL遇到了一些问题。. NET,所以我总是添加使用实体框架。它更容易操作。

这是你的问题如何与实体框架…

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();
}    

让我知道这是否适合你