简体   繁体   English

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

[英]When get data between two time on date time column, it does not return any rows - ASP.NET / C#

I work on an ASP.NET web forms project;我从事一个 ASP.NET web forms 项目; I can't get data between two times (time from and time to) on datetime column.我无法在 datetime 列的两次(时间从和时间到)之间获取数据。

C#function 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;
}  

When I try from SQL Server, it return 2 rows:当我从 SQL 服务器尝试时,它返回 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'

Expected result:预期结果:

在此处输入图像描述

I modified query to as below:我将查询修改为如下:

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

but still not get any result so what i do to solve issue但仍然没有得到任何结果所以我做了什么来解决问题

So, a few things:所以,有几件事:

Don't wrap long lines of code, they are VERY prone to errors.不要包装长行代码,它们很容易出错。

Looking at your SQL, you have this:看看你的 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"

Note how easy now we see "and and" in your SQL.请注意,现在我们在您的 SQL 中看到“and and”是多么容易。

And don't do those casts in the SQL, since it messy, but such expressions can't be indexed, and they will run turtle slow.并且不要在 SQL 中做那些转换,因为它很乱,但是这样的表达式不能被索引,而且它们运行起来会很慢。 (besides, it makes the SQL rather a mess to work with). (此外,它使 SQL 变得一团糟)。

next up: consider moving the in-line SQL out to a stored procedure, but even better (and less effort and work) is to use a view, and thus "less" work then a stored procedure, you can use the query builder/designer, and EVEN better is multiple routines can use that one "view".下一步:考虑将内联 SQL 移出存储过程,但更好(并且更少的努力和工作)是使用视图,因此比存储过程“更少”工作,您可以使用查询生成器/设计师,甚至更好的是多个例程可以使用一个“视图”。 You still use in-line SQL, but only say您仍然使用内联 SQL,但只说

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

next up:接下来:

Don't use add with value - use STRONG typed parameter's.不要使用 add with value - 使用 STRONG 类型的参数。

next up:接下来:

While using Parmaters.Add("some parm", "some value") is deprecated, since the 2nd parameter can be confused with int as dbtype?虽然不推荐使用 Parmaters.Add("some parm", "some value"),因为第二个参数可能与 int 混淆为 dbtype?

using typed parameter with "ADD" IS NOT deprecated,!!, and in fact I recommend using使用带有“ADD”的类型参数不被弃用,!!,事实上我建议使用

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

Again, above format is NOT deprecated, only the overload with a non dbtype for 2nd parameter in above is deprecated!!!同样,上面的格式没有被弃用,只有上面第二个参数的非 dbtype 的重载被弃用了!!!

Next up:接下来:

You don't show where that connection object is created.您不显示该连接 object 的创建位置。 DO NOT try to make some global scoped connection object. While before the "web days", for performance, yes, often we "persisted" a connection object, but with web based, there is a automatic "connection" pool, and thus the standard is to re-create the connection's each time, and LET THE SYSTEM AUTOMATIC dispose for you.不要尝试建立一些全局范围的连接 object。在“网络时代”之前,为了性能,是的,我们经常“坚持”连接 object,但是基于 web,有一个自动“连接”池,因此标准是每次都重新创建连接,让系统自动为您处理。 By doing this, you leverage the "automatic" connection system in .net web based system.通过这样做,您可以利用基于 .net web 的系统中的“自动”连接系统。

Re-creating the connection object each time is NOT a performance hit, since the connection pool will "find" and use cached connection - it runs fast - feel free to re-create connection object each time.每次重新创建连接 object 不会影响性能,因为连接池将“查找”并使用缓存连接 - 它运行速度很快 - 每次都可以随意重新创建连接 object。

And how do you LET the system manage this for you?你如何让系统为你管理这个? Why of course you ALWAYS wrap that code in using blocks.当然,为什么您总是将该代码包装在 using 块中。 In your example, you ONLY dispose of the connection when code errors, but not on success.在您的示例中,您仅在代码错误时处理连接,而不是在成功时处理连接。

next up:接下来:

As noted, don't try to parse out, or convert the date, and date time in the SQL, but supply STRONG types for start and end date (both with time).如前所述,不要尝试解析或转换 SQL 中的日期和日期时间,而是为开始日期和结束日期(均带有时间)提供 STRONG 类型。 Not only is such code less of a mess, but it also a "tiny" bit of work in the code, but the SQL becomes VAST VAST less messy.这样的代码不仅不那么混乱,而且代码中的“微小”工作也很少,但是 SQL 变得 VAST VAST 不那么混乱了。 So, we trade a "wee bit" of code for a HUGE bonus of nice clean SQL.因此,我们用“一点点”代码换取 nice clean SQL 的巨大奖励。

So, lets take all of the above lessons, and thus we get this now:所以,让我们吸取以上所有教训,因此我们现在得到了:

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

So, note how we let the system "close" the connection's, and dispose of it.因此,请注意我们如何让系统“关闭”连接并处理掉它。 And even if the code errors out, even when NOT trapped, the connection and command object will be correctly disposed and managed for you - IN ALL cases!!!即使代码出错,即使没有被困,连接和命令 object 也会为您正确处理和管理 - 在所有情况下!!!

Also, note how a bit of effort on the code side to get STRONG TYPED date start and end, thus makes the SQL part a whole lot less work, but MORE important also means that we use + enjoy STRONG typed values for the parameter's, and we enjoy use of high speed indexing.另外,请注意在代码方面如何获得 STRONG TYPED 日期的开始和结束,从而使 SQL 部分的工作量大大减少,但更重要的还意味着我们使用 + 享受参数的 STRONG 类型值,并且我们喜欢使用高速索引。

Always declare the type of parameter you're passing into SQL. Don't rely on sql to infer it.始终声明您传递给 SQL 的参数类型。不要依赖 sql 来推断它。 Also make a habit of wrapping your db connection in a Using block.还要养成将数据库连接包装在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;

You'll need to add code for the @branch and @ordertype parameters as well.您还需要为@branch 和@ordertype 参数添加代码。

Your SQL would look like the below.您的 SQL 如下所示。 When writing SQL, most mistakes can be managed by consistently formatting your SQL while you write it.在编写 SQL 时,大多数错误都可以通过在编写时始终如一地格式化 SQL 来解决。 Parameters do not need to be wrapped in quotes when you declare the data type of the param like I have above.当你像我上面那样声明参数的数据类型时,参数不需要用引号引起来。 It handles all that for you.它为您处理所有这些。 Rather than comparing the date separately, I opted to pass the times in as Time data type and then cast them to datetime inside the query.我没有单独比较日期,而是选择将时间作为时间数据类型传递,然后将它们转换为查询中的日期时间。 From there, you can add two date times together with the + and then do your comparison the same way.从那里,您可以将两个日期时间与+一起添加,然后以相同的方式进行比较。 If you decide to pass your to/from values in as datetime then just remove the declare line at the top.如果您决定将您的传入/传出值作为日期时间传递,则只需删除顶部的声明行。

You could use BETWEEN in the WHERE clause but that's at your discretion.您可以在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

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

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