为什么 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 格式。
使用此代码:
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 格式。