为什么 C# DateTime 与 SQLServer DateTime 不匹配?

Why does C# DateTime not match SQLServer DateTime?

使用此代码:

private void ReadData(String _unit, String _member, DateTime _dateBegin, 
    DateTime _dateEnd)
{
    try
    {
        DataTable dtFillRateResults =
            SqlDBHelper.ExecuteSQLReturnDataTable("sp_CRP_FillRate2",
            CommandType.StoredProcedure,
                new SqlParameter() { ParameterName = "@Unit", SqlDbType = SqlDbType.VarChar, Value = _unit },
                new SqlParameter() { ParameterName = "@Member", SqlDbType = SqlDbType.VarChar, Value = _member },
                new SqlParameter() { ParameterName = "@BegDate", SqlDbType = SqlDbType.DateTime, Value = _dateBegin },
                new SqlParameter() { ParameterName = "@EndDate", SqlDbType = SqlDbType.DateTime, Value = _dateEnd }
        );

...像这样传递 C# DateTime.Date 值:

frpg.GeneratePackets(clbCheckedUnitItems, clbCheckedMembersItems,   
    dateTimePickerFrom.Value.Date, dateTimePickerTo.Value.Date);
. . .
public void GeneratePackets(CheckedListBox.CheckedItemCollection selectedUnits, CheckedListBox.CheckedItemCollection selectedMembers, DateTime from, DateTime to)
{
    try
    {
        foreach (DataRowView drvu in selectedUnits)
        {
                . . .
                foreach (DataRowView drvm in selectedMembers)
                {
                    ReadData(unit, shortMemberName, from, to);
                    . . .

...它没有崩溃,但我没有返回任何记录。如果我像这样将 args 从 DateTime.Value.Date 更改为 DateTime.Value,效果也不会更好:

frpg.GeneratePackets(clbCheckedUnitItems, clbCheckedMembersItems,  
    dateTimePickerFrom.Value, dateTimePickerTo.Value);

如果我像这样将日期转换为 YYYMMDD 格式:

String dateBegin = FillRateRptConstsAndUtils.GetYYYYMMDD(_dateBegin, true);
String dateEnd = FillRateRptConstsAndUtils.GetYYYYMMDD(_dateEnd, false);
DataTable dtFillRateResults =
            SqlDBHelper.ExecuteSQLReturnDataTable("sp_CRP_FillRate2",
            CommandType.StoredProcedure,
                new SqlParameter() { ParameterName = "@Unit", SqlDbType = 
SqlDbType.VarChar, Value = _unit },
                new SqlParameter() { ParameterName = "@Member", SqlDbType = 
SqlDbType.VarChar, Value = _member },
                new SqlParameter() { ParameterName = "@BegDate", SqlDbType = 
SqlDbType.DateTime, Value = dateBegin },
                new SqlParameter() { ParameterName = "@EndDate", SqlDbType = 
SqlDbType.DateTime, Value = dateEnd }
        );

public static string GetYYYYMMDD(DateTime rawDate, bool startOfRange)
{
    int year = rawDate.Year;
    int month = rawDate.Month;
    String monthAsStr = month.ToString();
    if (monthAsStr.Length == 1)
    {
        monthAsStr = "0" + monthAsStr;
    }
    var dayVal = startOfRange ? "01" : GetLastDayOfMonth(month, 
year.ToString());
    if (dayVal.Length == 1)
    {
        dayVal = "0" + dayVal;
    }
    return String.Format("{0}{1}{2}", year, monthAsStr, dayVal);
}

public static string GetLastDayOfMonth(int monthAsInt, String year)
{
    int yearAsInt = Convert.ToInt32(year);
    DateTime d8 = new DateTime(yearAsInt, monthAsInt, 
DateTime.DaysInMonth(yearAsInt, monthAsInt));
    return d8.Day.ToString();
}

...我得到,“无法将参数值从字符串转换为 DateTime

最后,如果我尝试这个(将 YYYYMMDD 字符串转换为 DateTime):

    DataTable dtFillRateResults =
        SqlDBHelper.ExecuteSQLReturnDataTable("sp_CRP_FillRate2",
    CommandType.StoredProcedure,
        new SqlParameter() { ParameterName = "@Unit", SqlDbType = 
SqlDbType.VarChar, Value = _unit },
        new SqlParameter() { ParameterName = "@Member", SqlDbType = 
SqlDbType.VarChar, Value = _member },
        new SqlParameter() { ParameterName = "@BegDate", SqlDbType = 
SqlDbType.DateTime, Value = Convert.ToDateTime(dateBegin) },
        new SqlParameter() { ParameterName = "@EndDate", SqlDbType = 
SqlDbType.DateTime, Value = Convert.ToDateTime(dateEnd) }
    );

...我明白了,“字符串未被识别为有效的日期时间

那么这里的氦气是怎么回事?我怎样才能给 SQL 服务器它想要的东西?

更新

顺便说一句,执行SQLReturnDataSet() 是:

private static readonly int EXTENDED_TIMEOUT = 120;

public static DataSet ExecuteSQLReturnDataSet(string sql, CommandType cmdType, params SqlParameter[] parameters)
{
    using (DataSet ds = new DataSet())
    using (SqlConnection connStr = new SqlConnection(FillRateRptConstsAndUtils.CPSConnStr))
    using (SqlCommand cmd = new SqlCommand(sql, connStr))
    {
        cmd.CommandType = cmdType;
        cmd.CommandTimeout = EXTENDED_TIMEOUT;
        foreach (var item in parameters)
        {
            cmd.Parameters.Add(item);
        }

        try
        {
            cmd.Connection.Open();
            new SqlDataAdapter(cmd).Fill(ds);
        }
        catch (SqlException sqlex)
        {
            for (int i = 0; i < sqlex.Errors.Count; i++)
            {
                var sqlexDetail = String.Format("From ExecuteDataSet(), SQL Exception #{0}{1}Source: {2}{1}Number: {3}{1}State: {4}{1}Class: {5}{1}Server: {6}{1}Message: {7}{1}Procedure: {8}{1}LineNumber: {9}",
                    i + 1, // Users would get the fantods if they saw #0
                    Environment.NewLine,
                    sqlex.Errors[i].Source,
                    sqlex.Errors[i].Number,
                    sqlex.Errors[i].State,
                    sqlex.Errors[i].Class,
                    sqlex.Errors[i].Server,
                    sqlex.Errors[i].Message,
                    sqlex.Errors[i].Procedure,
                    sqlex.Errors[i].LineNumber);
                MessageBox.Show(sqlexDetail);
            }
        }
        catch (Exception ex)
        {
            String exDetail = String.Format(FillRateRptConstsAndUtils.ExceptionFormatString, ex.Message, Environment.NewLine, ex.Source, ex.StackTrace);
            MessageBox.Show(exDetail);
        }
        return ds;
    }
}

这个有效:

String dateBegin = 
    FillRateRptConstsAndUtils.GetYYYYDashMMDashDD(_dateBegin, true);
String dateEnd =
    FillRateRptConstsAndUtils.GetYYYYDashMMDashDD(_dateEnd, false);
DataTable dtFillRateResults =
    SqlDBHelper.ExecuteSQLReturnDataTable("sp_CRP_FillRate2",
        CommandType.StoredProcedure,
        new SqlParameter() { ParameterName = "@Unit", SqlDbType
= SqlDbType.VarChar, Value = _unit },
        new SqlParameter() { ParameterName = "@Member",
SqlDbType = SqlDbType.VarChar, Value = _member },
        new SqlParameter() { ParameterName = "@BegDate",
SqlDbType = SqlDbType.DateTime, Value = Convert.ToDateTime(dateBegin) },
        new SqlParameter() { ParameterName = "@EndDate",
SqlDbType = SqlDbType.DateTime, Value = Convert.ToDateTime(dateEnd) }
    );

public static string GetYYYYDashMMDashDD(DateTime rawDate, bool startOfRange)
{
    int year = rawDate.Year;
    int month = rawDate.Month;
    String monthAsStr = month.ToString();
    if (monthAsStr.Length == 1)
    {
        monthAsStr = "0" + monthAsStr;
    }
    var dayVal = startOfRange ? "01" : GetLastDayOfMonth(month, year.ToString());
    if (dayVal.Length == 1)
    {
        dayVal = "0" + dayVal;
    }
    return String.Format("{0}-{1}-{2}", year, monthAsStr, dayVal);
}

IOW,传递给 ConvertToDateTime() 的值必须采用 YYYY-MM-DD 格式。