在日期时间列上获取两个时间之间的数据时,它不返回任何行 - ASP.NET / C#

问题描述 投票:0回答:2

我从事 ASP.NET Web 表单项目;我无法在日期时间列上获取两个时间(时间从和时间到)之间的数据。

C#函数

public DataTable GetDataForSearch(string datelogged, string FromTime, string ToTime)
{
    string response = string.Empty;

    SqlCommand cmd = new SqlCommand();
    DataTable dt = new DataTable();

    try
    {
            conn.Open();
            cmd.Connection = conn;
            cmd.CommandText = "select datelogged AS EntredDatetime, Doc_type AS OrderType, Printer_name, BranchID AS BranchCode, Status, id from Print_Report where cast(datelogged as date)=@datelogged  and and FORMAT(CAST(datelogged AS DATETIME), 'HH:mm')>'@FromTime' AND FORMAT(CAST(datelogged AS DATETIME), 'HH:mm')<@ToTime";
            cmd.CommandType = CommandType.Text;
            cmd.CommandTimeout = 50000;

            cmd.Parameters.AddWithValue("@datelogged", datelogged);
            cmd.Parameters.AddWithValue("@FromTime", FromTime);
            cmd.Parameters.AddWithValue("@ToTime", ToTime);

            SqlDataAdapter sda = new SqlDataAdapter(cmd);
            sda.Fill(dt);
        }
        catch (Exception ex)
        {
            response = ex.Message;
        }
        finally
        {
            cmd.Dispose();
            conn.Close();
        }

        return dt;
}  

当我从 SQL Server 尝试时,它返回 2 行:

select 
    datelogged as EntredDatetime, Doc_type as OrderType, 
    Printer_name, BranchID as BranchCode, Status, id 
from 
    Print_Report 
where 
    BranchID = '10207' 
    and cast(datelogged as date) = '2010-07-05' 
    and Doc_type = 'BP'  
    and format(cast(datelogged as DATETIME), 'HH:mm') > '13:30' 
    and format(cast(datelogged as DATETIME), 'HH:mm') < '14:00'

预期结果:

enter image description here

我将查询修改为如下:

  cmd.CommandText = "select datelogged AS EntredDatetime, Doc_type AS OrderType, Printer_name, BranchID AS BranchCode, Status, id from Print_Report where BranchID=@BranchCode and cast(datelogged as date)=@datelogged and Doc_type=@OrderType and  FORMAT(CAST(datelogged AS DATETIME), 'HH:mm')>='@FromTime' AND FORMAT(CAST(datelogged AS DATETIME), 'HH:mm')<='@ToTime'";

但仍然没有得到任何结果 那么我要做什么来解决问题

c# asp.net webforms asp.net-webpages
2个回答
0
投票

始终声明要传递到 SQL 中的参数类型。不要依赖 sql 来推断它。还要养成将数据库连接包装在

Using
块中的习惯。

cmd.Parameters.Add("@datelogged", sqldbtype.datetime).value = datelogged;
cmd.Parameters.Add("@FromTime", sqldbtype.time).value = FromTime;
cmd.Parameters.Add("@ToTime", Sqldbtype.time).value = ToTime;

您还需要为 @branch 和 @ordertype 参数添加代码。

您的 SQL 将如下所示。编写 SQL 时,大多数错误都可以通过在编写 SQL 时一致地格式化 SQL 来解决。当您像上面那样声明参数的数据类型时,参数不需要用引号引起来。它会为你处理这一切。我没有单独比较日期,而是选择将时间作为时间数据类型传递,然后将它们转换为查询中的日期时间。从那里,您可以将两个日期时间与

+
一起添加,然后以相同的方式进行比较。如果您决定将传入/传出值作为日期时间传递,则只需删除顶部的声明行即可。

您可以在

BETWEEN
子句中使用
WHERE
,但这由您自行决定。


DECLARE @To DATETIME = (@datelogged + CAST(@ToTime AS DATETIME)), @From DATETIME = (@datelogged + CAST(@FromDate AS DATETIME));

SELECT
    datelogged AS EntredDatetime, 
    Doc_type AS OrderType, 
    Printer_name, 
    BranchID AS BranchCode, 
    Status,
    ID
FROM Print_Report 
WHERE BranchID = @BranchCode AND 
    Doc_type = @OrderType AND 
    datelogged >= @From AND 
    datelogged <= @To

0
投票

那么,有几件事:

不要将长行代码换行,它们很容易出错。

查看您的 SQL,您有以下内容:

  select datelogged AS EntredDatetime, Doc_type AS OrderType, Printer_name,
  BranchID AS BranchCode, Status, id from Print_Report 
  where cast(datelogged as date)=@datelogged
  and and FORMAT(CAST(datelogged AS DATETIME), 'HH:mm')>'@FromTime'
  AND FORMAT(CAST(datelogged AS DATETIME), 'HH:mm')<@ToTime"

请注意,现在我们在 SQL 中看到“and and”是多么容易。

并且不要在 SQL 中执行这些转换,因为它很混乱,但是这样的表达式无法索引,并且它们运行速度会很慢(此外,它使 SQL 处理起来相当混乱)。

下一步:考虑将内联 SQL 移出到存储过程,但更好(并且更少的精力和工作)是使用视图,因此比存储过程“更少”工作,您可以使用查询生成器/designer,更好的是多个例程可以使用该一个“视图”。你仍然使用内联SQL,但只是说

 select * from vPrint_Report
 WHERE datelogged is BETWEEN @dtStart AND @dtEnd";

接下来:不要使用带有值的 add - 使用强类型参数。

下一步:不推荐使用

Parameters.Add("some param", "some value")
,因为第二个参数可能与 int 作为 dbtype 混淆?

不推荐使用带有“ADD”的类型化参数!事实上,我建议使用

 .ADD("@ParmName", sqlDbType.int).Value = 

仅上面第二个参数具有非 dbtype 的重载已被弃用!

接下来:

您没有显示该连接对象的创建位置。不要尝试创建一些全局范围的连接对象。虽然在“网络时代”之前,为了性能,是的,我们经常“坚持”一个连接对象,但是基于网络,有一个自动“连接”池,因此标准是每次都重新创建连接,并让系统自动为您处理。通过这样做,您可以利用 .net 基于网络的系统中的“自动”连接系统。

每次重新创建连接对象不会影响性能,因为连接池将“查找”并使用缓存的连接 - 它运行速度很快 - 每次都可以随意重新创建连接对象。

你如何让系统为你管理这个?当然,为什么你总是将代码包装在 using 块中。在您的示例中,您仅在代码错误时处理连接,但在成功时不处理连接。

接下来:

如上所述,不要尝试解析或转换 SQL 中的日期和日期时间,而是为开始日期和结束日期(均带有时间)提供 STRONG 类型。这样的代码不仅不那么混乱,而且代码中的工作也“很小”,但 SQL 变得不那么混乱了。因此,我们用少量代码换取了干净 SQL 的巨大好处。

所以,让我们学习上述所有课程,现在我们明白了:

public DataTable GetDataForSearch(string datelogged, string FromTime, string ToTime)
{

    DataTable dt = new DataTable();
    string strCon = Properties.Settings.Default.TEST4; // change to YOUR connection

    using (SqlConnection conn = new SqlConnection(strCon))
    {
        string strSQL =
            @"select datelogged AS EntredDatetime, Doc_type AS OrderType, 
            Printer_name, BranchID AS BranchCode, Status, id
            FROM Print_Report
            WHERE datelogged is BETWEEN @dtStart AND @dtEnd";

        DateTime dtDate = DateTime.Parse(datelogged);
        DateTime dtFromTime = DateTime.Parse(FromTime);
        DateTime dtToTime = DateTime.Parse(ToTime);

        DateTime dtStart = 
          dtDate.Add(new TimeSpan(dtFromTime.Hour, dtFromTime.Minute, dtFromTime.Second));

        DateTime dtEnd =
          dtDate.Add(new TimeSpan(dtToTime.Hour, dtToTime.Minute, dtToTime.Second)); 

            
        using (SqlCommand cmd = new SqlCommand(strSQL, conn))
        {
            cmd.Parameters.Add("@dtStart", SqlDbType.DateTime).Value = dtStart;
            cmd.Parameters.Add("@dtEnd", SqlDbType.DateTime).Value = dtEnd;

            try
            {
                conn.Open();
                dt.Load(cmd.ExecuteReader());
            }
        }
    }
    return dt;
}

因此,请注意我们如何让系统“关闭”连接并处理它。即使代码出错,即使没有被捕获,连接和命令对象也将被正确处理和管理 - 在所有情况下!

另外,请注意如何在代码方面付出一些努力来获取强类型日期开始和结束,从而使 SQL 部分的工作量减少很多,但更重要的是也意味着我们使用 + 享受参数的强类型值,我们喜欢使用高速索引。

© www.soinside.com 2019 - 2024. All rights reserved.