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

btxsgosb  于 2023-02-01  发布在  .NET
关注(0)|答案(2)|浏览(182)

我从事ASP.NET网页表单项目;我无法在datetime列中获取两个时间(时间开始和时间结束)之间的数据。
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'

预期结果:

我将质询修改为:

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'";

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

qlckcl4x

qlckcl4x1#

一定要声明你传递给SQL的参数类型,不要依赖sql来推断它,还要养成把你的数据库连接 Package 在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;

您还需要为@分支和@ordertype参数添加代码。
您的SQL将如下所示。在编写SQL时,大多数错误都可以通过在编写时一致地格式化SQL来管理。在声明param的数据类型时,参数不需要用引号括起来,就像我上面所做的那样。它会为您处理所有这些问题。而不是分别比较日期。我选择将时间作为Time数据类型传入,然后在查询中将其转换为datetime。您可以将两个日期时间与+相加,然后以相同的方式进行比较。如果您决定将您的传递给/从作为日期时间的值中删除顶部的声明行。
您可以在WHERE子句中使用BETWEEN,但这由您自行决定。

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
pb3skfrl

pb3skfrl2#

所以,有几件事:
不要 Package 长代码行,它们很容易出错。
看看您的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移到存储过程中,但更好的方法(更少的工作和精力)是使用视图,因此比存储过程"更少"工作,您可以使用查询构建器/设计器,更好的方法是多个例程可以使用一个"视图"。

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

接下来:
不要使用带值的加法-使用STRONG类型参数。
接下来:
在使用Parmaters时,Add("some parm","some value")被弃用,因为第二个参数可能会与作为dbtype的int混淆。
使用带"ADD"的类型化参数并不过时!!!,事实上我推荐使用

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

同样,上述格式并不过时,只有上述第二个参数为非dbtype的重载才过时!!!
接下来:
你没有显示连接对象是在哪里创建的。不要试图创建一些全局范围的连接对象。在"web时代"之前,为了性能,是的,我们经常"持久化"一个连接对象,但是对于基于web的,有一个自动的"连接"池,因此标准是每次重新创建连接,让系统自动为你处理。通过这样做,你在基于. netweb的系统中利用"自动"连接系统。
每次重新创建连接对象不会影响性能,因为连接池将"找到"并使用缓存的连接-它运行速度很快-您可以随时重新创建连接对象。
你如何让系统为你管理这个呢?为什么你总是用块来 Package 代码呢?在你的例子中,你只在代码错误时处理连接,而不是在成功时。
接下来:
如前所述,不要试图解析或转换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 conneciton

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

所以,请注意我们是如何让系统"关闭"连接的,并处理它的。即使代码出错,即使没有被捕获,连接和命令对象也会被正确地处理和管理-在所有情况下!!!
此外,请注意在代码端如何获得STRONG TYPED日期的开始和结束,从而使SQL部分的工作量大大减少,但更重要的是还意味着我们使用+享受STRONG类型的参数值,我们享受使用高速索引。

相关问题