可以过滤日期,但不能过滤日期时间?
我有一个应用程序,可以使用datetimepicker基于日期过滤datagridview。我的数据库中的“日期”列是日期时间数据类型,因此它将包含存储在其中的日期和时间,但有一些数据只有日期。我的问题是我的datetimepicker过滤器只能用date = 12:00:00 AM过滤这些数据。那些包含其他时间的数据在使用datatimepicker选择日期时无法过滤。我不知道有什么问题。这里是我的代码:可以过滤日期,但不能过滤日期时间?
public trackInput()
{
InitializeComponent();
dataGridView1.Visible = false;
webBrowser1.Location = new Point(12, 141);
}
/*private void trackInput_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'trackingBMSDATADataSet.BRDATA' table. You can move, or remove it, as needed.
this.bRDATATableAdapter.Fill(this.trackingBMSDATADataSet.BRDATA);
}*/
private void trackBtn_Click(object sender, EventArgs e)
{
dataGridView1.Visible = true;
if (dataGridView1.Visible == true)
{
webBrowser1.Location = new Point(12, 397);
}
//DataTable dt = null;
string connoInput = textBox1.Text;
string conString = Properties.Settings.Default.BMSDATAConnectionString;
using (SqlCeConnection con = new SqlCeConnection(@"Data Source=C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\TrackCon\TrackCon\BMSDATA.sdf;Persist Security Info = True;Password=Gdex123$"))
{
string Ids = "conno= '" + System.Text.RegularExpressions.Regex.Replace(textBox1.Text.Trim(), @"\s*\n\s*", "' OR conno= '") + "'";
SqlCeCommand com = new SqlCeCommand("SELECT conno,cmpsno,ctrx,dsysdate,cstnno,corigin FROM BRDATA WHERE " +Ids, con);
SqlCeDataAdapter adap = new SqlCeDataAdapter(com);
DataSet set = new DataSet();
adap.Fill(set);
if (set.Tables.Count > 0)
{
bRDATABindingSource1.DataSource = set.Tables[0];
}
bRDATABindingSource1.Filter = null;
dataGridView1.DataSource = bRDATABindingSource1;
con.Close();
}
}
private void trackMPSbtn_Click(object sender, EventArgs e)
{
dataGridView1.Visible = true;
if (dataGridView1.Visible == true)
{
webBrowser1.Location = new Point(12, 397);
}
//DataTable dt = null;
//string connoInput = textBox1.Text;
string conString = Properties.Settings.Default.BMSDATAConnectionString;
using (SqlCeConnection con = new SqlCeConnection(@"Data Source=C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\TrackCon\TrackCon\BMSDATA.sdf;Persist Security Info = True;Password=Gdex123$"))
{
dataGridView1.DataSource = bRDATABindingSource1;
string Ids = "cmpsno= '" + System.Text.RegularExpressions.Regex.Replace(textBox2.Text.Trim(), @"\s*\n\s*", "' OR cmpsno= '") + "'";
con.Open();
SqlCeCommand com = new SqlCeCommand("SELECT conno,cmpsno,ctrx,dsysdate,cstnno,corigin FROM BRDATA WHERE " + Ids, con);
SqlCeDataAdapter adap = new SqlCeDataAdapter(com);
DataSet set = new DataSet();
adap.Fill(set);
if (set.Tables.Count > 0)
{
bRDATABindingSource1.DataSource = set.Tables[0];
}
bRDATABindingSource1.Filter = null;
dataGridView1.DataSource = bRDATABindingSource1;
con.Close();
}
}
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
bRDATABindingSource1.Filter = string.Format("dsysdate = #{0:d/M/yyyy HH:mm tt}#", dateTimePicker1.Value.ToLongDateString());
}
DateTimePicker具有包含选定日期的属性值。你应该使用这个日期,形成一个查询看起来像这样:
where somedate >= datetimepicker.Value.Date
and somedate < datetimepicker.Value.Date.AddDays(1)
其中.Date只返回日期时间的日期部分。为了准备where子句中,替换其中具有
" where conno >= @startDate and conno < @endDate"
SqlCeCommand的部分添加两个参数SqlCeCommand
com.Parameters.Add (new SqlCeParameter("@startDate", SqlDbType.DateTime,
textbox1.Value.Date));
com.Parameters.Add (new SqlCeParameter("@endDate", SqlDbType.DateTime,
textbox1.Value.Date.AddDays(1)));
,做类似的活动与cmpsno。
更新:我完全错过了最后的方法。
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
bRDATABindingSource1.Filter = string.Format("dsysdate >= '{0:yyyy-MM-dd}' AND dsysdate < '{1:yyyy-MM-dd}'", dateTimePicker1.Value, dateTimePicker1.Value.AddDays(1));
}
在解释的努力:
由于dsysdate有你需要的过滤从午夜开始,并延伸至次日午夜的间隔时间组件 - 这是Value.AddDays(1)。不幸的是,我对Filter BindingSource的过滤知之甚少,因为我主要是在数据库级别进行过滤,因此我首先进行了过滤。您可能需要重写dateTimePicker1_ValueChanged以从数据库中检索数据,而不是在内存中进行筛选;当由于索引而使用较大的表格时,它会得到回报。说到这一点,你可能会考虑以不同的方式构建你的代码。这样的任务通常是通过一种方法来完成的,该方法检查过滤控件,构建查询并执行它,从而消除重复的代码并允许您一次过滤多个条件。方法比过滤控件的内容更改时被调用。
我有几点意见:
1:串联文本永远不要编写查询。即使您尝试清理输入,也会受到SQL注入的影响。改为使用存储过程或参数化查询:它们完全免疫SQL注入。
第二:使用参数,因为您可以简单地传递原始形式的值,而不是将它们转换为文本。这将消除部分问题。您可以使用存储过程或参数化查询。
2nd & 1/2:还有其他原因使用参数,这与性能有关。
第3:可能按日期时间过滤将起作用,但您无法保证。您是否希望用户能够按照确切的日期时间进行过滤,包括秒和几分之一秒?我认为这不是一个好主意。请重新设计它或解释你想要做什么。它看起来没有多少意义。也许你应该在将日期存储在数据库之前将日期“舍入”到几秒或几分钟。你应该考虑日期时间不准确。它的工作原理有点像浮点数,所以你可以直接比较这些数值而不会有问题。也就是说,我等待您的意见来帮助您改进设计。
增加: 至于你说的部分时间并不重要,你可以插入删除,或在比较(在比较与参数datetime列),使用这个“绝招”:
SELECT (CAST(FLOOR(CAST(YourDateTimeColumn as FLOAT)) AS DateTime))
日期在内部存储为从基准日起的天数。小数部分表示一天中的小数部分(hh:mm:ss ...)。所以,如果你摆脱了小数,你只保留日期部分,并且可以安全地将它与给定日期进行比较。
如果您不需要时间部分:如果您使用的是SQL Server 2008或更高版本,则可以对列使用DATE类型(如果您不需要存储时间)。或者,您可以在将数据插入以前版本的SQL Server时使用相同的技巧。
感谢提示。我会牢记并改进它。我在c#环境中仍然是新手,仍然在努力提高自己。对于第三条评论,当然用户不需要插入时间的确切细节。用户只需要选择一个日期,datagridview将根据选择的日期进行过滤。但正如我所说,在选择日期之后,过滤器只能检测到包含time = 12:00:00 AM的数据。那些含有其他时间的数据不能被检测到被过滤。 – 2012-03-28 01:35:51
请看看如何摆脱datetime部分。还有其他一些方法,但我认为这是更快。 – JotaBe 2012-03-28 02:08:14
对不起,理论上我理解它是如何工作的,但我不太清楚我需要放置哪些代码部分。我尽量把它放在这儿: '私人无效dateTimePicker1_ValueChanged(对象发件人,EventArgs的) {SqlCeCommand厘米= 新SqlCeCommand( “SELECT(CAST(FLOOR(CAST(dsysdate为FLOAT) 为DATETIME))FROM BRDATA” ); bRDATABindingSource1.Filter = 的String.Format ( “dsysdate =#{0:DD/MM/YYYY}#”,dateTimePicker1.Value.ToLongDateString());} ' 但是当我运行,所述 – 2012-03-28 02:23:54
对不起尼古拉,但我不太明白,你能解释一下吗? – 2012-03-28 02:07:41
@ shahrul1509请参阅更新 – 2012-03-28 07:36:21
感谢您的建议@尼古拉。 textboxt实际上是一个文本框。我的应用程序的总功能实际上是它有两个过滤器。一个是按ID过滤。用户可以输入ID,系统将显示ID信息。然后用户可以通过使用datetimepicker选择日期来进一步过滤该信息。我的问题在于日期过滤器。文本框过滤器工作正常。:) – 2012-03-28 07:40:19