我写了这个SQL语句,然后我的SQL服务器正在运行。
SELECT r.RentID,c.CustomerName,v.VehicleName,r.[Hours], r.[Hours] * v.Rent AS Total FROM Rent as r
INNER JOIN Customer AS c ON r.CustomerID = c.CustomerID
INNER JOIN Vehicle AS v ON r.VehicleID = v.VehicleID
此外,当我使用C#编写时,它不会显示,尽管某些SQL语句(如Add,Update,Delete)正常运行。 我想问一下我错在哪里以及如何解决它。非常感谢你。
public IList getRents()
{
IList result = new List();
try
{
SqlConnection con = new SqlConnection(sCon);
String query = "SELECT r.RentID,c.CustomerName,v.VehicleName,r.[Hours], r.[Hours] * v.Rent AS Total FROM Rent as r INNER JOIN Customer AS c ON r.CustomerID = c.CustomerID INNER JOIN Vehicle AS v ON r.VehicleID = v.VehicleID";
//String query = "SELECT * FROM Rent";
SqlCommand com = new SqlCommand(query, con);
con.Open();
SqlDataReader reader = com.ExecuteReader();
while (reader.Read())
{
Rent r = new Rent();
r.rentID = (int)reader[0];
r.customerID = (int)reader[1];
r.vehicleID = (int)reader[2];
r.hours = (int)reader[3];
//r.total = (int)reader[4];
result.Add(r);
}
con.Close();
}
catch (Exception ex)
{
ex.ToString();
}
return result;
}
答案 0 :(得分:2)
您似乎正在尝试将SQL列CustomerName
(可能是VARCHAR
或某种类型的字符串兼容类型)映射到int
。< / p>
Rent r = new Rent();
r.rentID = (int)reader[0];
r.customerID = (int)reader[1]; // here's your problem: reader[1] is CustomerName
r.vehicleID = (int)reader[2];
r.hours = (int)reader[3];
//r.total = (int)reader[4];
result.Add(r);
你如何解决它取决于你想要完成的事情。
如果您需要CustomerName
而非CustomerId
,则需要向string
模型添加名为CustomerName且属性为Rent
的属性,并更新您的读者:
Rent r = new Rent();
r.rentID = (int)reader[0];
r.customerName = (string)reader[1]; // updated
r.vehicleID = (int)reader[2];
r.hours = (int)reader[3];
//r.total = (int)reader[4];
result.Add(r);
如果您需要CustomerId
,则需要更改SQL:
SELECT r.RentID, c.CustomerId, v.VehicleName, r.[Hours], r.[Hours] * v.Rent AS Total FROM Rent as r INNER JOIN Customer AS c ON r.CustomerID = c.CustomerID INNER JOIN Vehicle AS v ON r.VehicleID = v.VehicleID
您的代码存在一些问题,导致您无法调试错误。
首先,您正在捕捉任何可能被抛出并吞噬它们的异常。 getRents()
将始终成功返回,但如果有任何错误,则会返回空的List
并且您永远不会知道原因。我的猜测是,为什么你要说&#34;它没有显示&#34;。
出于调试目的,请删除try catch
块。您可以稍后添加,但只有在您计划对异常执行某些操作时才会添加,例如显示友好的错误消息和/或记录它们。
当您运行没有try catch
块的代码时,它会抛出一个异常,以帮助您找出错误。
还有一些其他问题。在实现using
的对象上使用IDisposable
语句通常是个好主意。确定它们是否有效的快速简便方法是初始化它,然后查看是否有.Dispose
方法:
var conn = new SqlConnection();
conn.Dispose();
如果conn.Dispose()
没有编译器错误,或者Intellisense将其显示为有效方法,那么该对象是一次性的,您应该使用using
语句:
using(var conn = new SqlConnection())
{
// ...
}
处置一次性对象有助于防止内存泄漏并释放您不再需要的资源。此外,它可以让你做这样的事情:
public IList getRents()
{
using (var con = new SqlConnection(sCon))
{
var query = "SELECT r.RentID,c.CustomerName,v.VehicleName,r.[Hours], r.[Hours] * v.Rent AS Total FROM Rent as r INNER JOIN Customer AS c ON r.CustomerID = c.CustomerID INNER JOIN Vehicle AS v ON r.VehicleID = v.VehicleID";
using (var com = new SqlCommand(query, con))
{
con.Open();
using (var reader = com.ExecuteReader())
{
IList result = new List<Rent>();
while (reader.Read())
{
Rent r = new Rent();
r.rentID = (int)reader[0];
r.customerID = (int)reader[1];
r.vehicleID = (int)reader[2];
r.hours = (int)reader[3];
//r.total = (int)reader[4];
result.Add(r);
}
return result;
}
}
}
}
我重构了你的方法,以便更容易阅读和调试。请注意,在return
完成后立即调用SqlDataReader
而不是在方法的最后。这使您可以使变量更接近他们使用的位置,在本例中为result
。这样可以更容易地找到潜在问题并纠正出现的异常。
最后,由于getRents
实际上只从SQL到C#对象的映射,我认为像Dapper这样的微型ORM会对你有很大的帮助。这更像是个人决定,但如果您的应用程序正在进行大量的CRUD工作,那么像Dapper这样的微型ORM会大大减少写入时间以及降低潜在问题。
使用Dapper考虑这个重构版本:
public IList GetRents()
{
using(var conn = new SqlConnection(sCon))
{
var query = "SELECT r.RentID,c.CustomerName,v.VehicleName,r.[Hours], r.[Hours] * v.Rent AS Total FROM Rent as r INNER JOIN Customer AS c ON r.CustomerID = c.CustomerID INNER JOIN Vehicle AS v ON r.VehicleID = v.VehicleID";
return conn.Query<Rent>(sql).ToList();
}
}
正如您所看到的,它更短,更简单,更直接。只需确保您的类属性与您的SQL列名称匹配。 Stack Overflow使用Dapper;事实上,他们开发了它。阅读更多相关信息here。
答案 1 :(得分:1)
您正在将所有内容都转换为int。澄清您是否需要代码中的名称或ID。如果您需要ID,请将查询更改为
String query = "SELECT r.RentID,c.CustomerID,v.VehicleID,r.[Hours], r.[Hours] * v.Rent AS Total FROM Rent as r INNER JOIN Customer AS c ON r.CustomerID = c.CustomerID INNER JOIN Vehicle AS v ON r.VehicleID = v.VehicleID";
如果是您想要的名称,则将相应的字段更改为强制转换为字符串。同时检查乘以r.Hours * v.Rent
生成的数据类型,因为这可能会无意中舍入您注释掉的行的结果。
您从未指定过您获得的例外情况。它可能会失败,因为您将字符串(2个名称)转换为整数。实际上,您的代码会吞下任何异常并且不会报告或记录它,因此找到问题的确切来源并不容易。
在异常处理程序中考虑这个
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
然后检查“输出”窗口,查看您遇到的错误。并把它放在这里,这样我们可以更好地帮助。
答案 2 :(得分:-3)
试试吧。 在您的代码中,您有一个&#34; *&#34;最
public IList getRents()
{
IList result = new List();
try
{
SqlConnection con = new SqlConnection(sCon);
String query = "SELECT r.RentID,c.CustomerName,v.VehicleName,r.[Hours], r.[Hours] , v.Rent AS Total FROM Rent as r INNER JOIN Customer AS c ON r.CustomerID = c.CustomerID INNER JOIN Vehicle AS v ON r.VehicleID = v.VehicleID";
//String query = "SELECT * FROM Rent";
SqlCommand com = new SqlCommand(query, con);
con.Open();
SqlDataReader reader = com.ExecuteReader();
while (reader.Read())
{
Rent r = new Rent();
r.rentID = (int)reader[0];
r.customerID = (int)reader[1];
r.vehicleID = (int)reader[2];
r.hours = (int)reader[3];
//r.total = (int)reader[4];
result.Add(r);
}
con.Close();
}
catch (Exception ex)
{
ex.ToString();
}
return result;
}