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注入打开了大门。试试相反:
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
块由于错误或return
或break
语句而过早地离开,它也会这样做。你关闭了两次连接。在下面的示例中,我使用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();
}
让我知道这是否适合你