在C#中选择条件,它是不可见的

时间:2017-06-22 16:41:13

标签: c# sql-server

我写了这个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;
}

3 个答案:

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