简体   繁体   English

C#将数据库提取到SQL Server数据表中

[英]c# fetching database into SQL Server datatable

I have a problem with this code... I don't have the slightest clue for what is happening... 我的这段代码有问题...我对发生的事情一无所知...

When I run this code in Visual Studio, I get an error saying: 在Visual Studio中运行此代码时,出现错误消息:

System.InvalidCastException: 'Object cannot be cast from DBNull to other types.' System.InvalidCastException:'无法将对象从DBNull强制转换为其他类型。

And here's the code: 这是代码:

conn.Open();

SqlCommand com = new SqlCommand("update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='" + comboBox1.Text + "'", conn);

SqlDataAdapter da = new SqlDataAdapter("Declare @startdate smalldatetime declare @enddate smalldatetime set @startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "') set @enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "') SELECT DATEDIFF(DAY, @startdate+2, @enddate)as timepassedd", conn);

DataTable dt = new DataTable();
da.Fill(dt);

foreach (DataRow DR in dt.Rows)
{
    int date;
    date = Convert.ToInt32(DR["timepassedd"]);

    if (date > 0)
    {
        com = new SqlCommand("DELETE lend WHERE client_name ='"+comboBox1.Text+"'" +
                             "UPDATE book_list set book_stock = book_stock  1 WHERE book_name ='" + comboBox1.Text + "'",conn);
        com.ExecuteNonQuery();

        MessageBox.Show("You Returned the book " + date + " Days Late!" +
                            "please pay the fee to the front desk");

        UserPanel u = new UserPanel();
        u.Show();

        this.Hide();
    }
    else if (date <= 0)
    {
        com = new SqlCommand("DELETE lend WHERE client_name ='" + comboBox1.Text + "'" +
                             "UPDATE book_list set book_stock = book_stock  1 WHERE book_name ='" + comboBox1.Text + "'", conn);
        com.ExecuteNonQuery();

        MessageBox.Show("You returned the book " + date + " Days Late!" +
                            "please pay the fee to the front desk");

        UserPanel u = new UserPanel();
        u.Show();

        this.Hide();
    }
}

conn.Close();

Thanks in advance 提前致谢

Run code below the answer will be obvious : 答案下面的运行代码将很明显:

                string sql1 = "update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='" + comboBox1.Text + "'";
                Console.WriteLine(sql1);
                Console.ReadLine();
                SqlCommand com = new SqlCommand(sql1, conn);
                string sql2 = "Declare @startdate smalldatetime declare @enddate smalldatetime set @startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "') set @enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "') SELECT DATEDIFF(DAY, @startdate+2, @enddate)as timepassedd"
                Console.ReadLine();
                SqlDataAdapter da = new SqlDataAdapter(sql2, conn);
        conn.Open();
        SqlCommand com = new SqlCommand("update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='" + comboBox1.Text + "'", conn);
        SqlDataAdapter da = new SqlDataAdapter("Declare @startdate smalldatetime declare @enddate smalldatetime set @startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "') set @enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "') SELECT DATEDIFF(DAY, @startdate+2, @enddate)as timepassedd", conn);
        DataSet ds = new DataSet();
        da.Fill(ds);
        if(ds.Tables.Count == 1)
        {
            if(ds.Tables[0].Rows.Count > 0)
            {
                foreach(DataRow dr in ds.Tables[0].Rows)
                {
                    if(dr.ItemArray.Length > 0)
                    {
                        if(dr["timepassedd"] != DBNull.Value)
                        {
                            int date;
                            date = Convert.ToInt32(Dr["timepassedd"]);
                            if (date > 0)
                            {
                                com = new SqlCommand("delete lend where client_name ='" + comboBox1.Text + "'" +
                                    "UPDATE book_list set book_stock = book_stock  1 WHERE book_name ='" + comboBox1.Text + "'", conn);
                                com.ExecuteNonQuery();
                                MessageBox.Show("You Returned the book " + date + " Days Late!" +
                                    "please pay the fee to the front desk");
                                UserPanel u = new UserPanel();
                                u.Show();
                                this.Hide();
                            }
                            else if (date <= 0)
                            {
                                com = new SqlCommand("delete lend where client_name ='" + comboBox1.Text + "'" +
                                    "UPDATE book_list set book_stock = book_stock  1 WHERE book_name ='" + comboBox1.Text + "'", conn);
                                com.ExecuteNonQuery();
                                MessageBox.Show("You Returned the book " + date + " Days Late!" +
                                    "please pay the fee to the front desk");
                                UserPanel u = new UserPanel();
                                u.Show();
                                this.Hide();
                            }
                        }
                    }
                }
            }
        }
        conn.Close();

You should check for DBNull value, if the column is null-able in the database a DBNull.Value will be returned instead! 您应该检查DBNull值,如果该列在数据库中可以为空,则将返回DBNull.Value So you should check this column for such a value before dealing with it 因此,在处理此列之前,应检查此列是否具有此类值
Also, you shouldn't accept values from the user input and directly injecting them into the SQL query! 同样,您不应该接受来自用户输入的值并将其直接注入SQL查询中! ADO.Net . ADO.Net Has something called Sql Parameters it can be found in the property Parameters in the SqlCommand class. 可以在SqlCommand类的Parameters属性中找到名为Sql Parameters东西。 You should use this property to add values from user as parameters to the query 您应该使用此属性将用户的值作为参数添加到查询中
For Example, client name can be added like this: 例如,可以这样添加客户端名称:

    com.Parameters.Add(new SqlParameter("client_name", comboBox1.Text));

Now you tell the Sql Command that the value is actually presented in the SqlParameters collection like this: 现在,您告诉Sql Command,该值实际上是在SqlParameters集合中呈现的,如下所示:

SqlCommand com = new SqlCommand("update lend set date_back=convert(datetime2, getdate(), 102) where client_name ='@client_name'", conn);

Take a look at this question Why do we always prefer using parameters in the SQL statements? 看看这个问题, 为什么我们总是喜欢在SQL语句中使用参数?
This is a MSDN reference for the Parameters property 这是Parameters属性的MSDN参考

set @startdate = (select date_lended from dbo.lend where client_name = '" + comboBox1.Text + "')
set @enddate = (select date_back from dbo.lend where client_name = '" + comboBox1.Text + "')

a) vulnerable to unexpected behaviour if comboBox1.Text was ever to contain ' characters a)如果comboBox1.Text曾经包含'字符,则容易发生意外行为

b) both will result in @startdate or @enddate being NULL if there are no records matching what's selected in the combobox, which then produces a NULL value for '@datepassedd', hence your error when trying to convert to an int. b)如果没有与组合框中所选内容匹配的记录,则两者都会导致@startdate或@enddate为NULL,然后为'@datepassedd'生成NULL值,因此在尝试转换为int时出错。

c) you don't need to query the database twice, you can just do c)您不需要两次查询数据库,您只需执行

select DATEDIFF(DAY, date_lended+2, date_back) as timepassedd FROM dbo.lend where client_name = @clientName

(@clientName can then be added a as parameter) (然后可以将@clientName添加为参数)

In this case, there will be no rows returned if no records match the name. 在这种情况下,如果没有记录与名称匹配,将不会返回任何行。 BTW there was never any need to use a DataTable and iterate through the records, as your query as it is now only ever returns a single row. 顺便说一句,您永远不需要使用DataTable并遍历记录,因为现在的查询只返回一行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM