1. Turn on Option Strict
Dim vDateFrom As Date = sDateFrom.Text
' or:
vDateFrom = "2016-03-01"
Code such as this will not compile: you cannot assign a string to a date or vice versa. They are 2 different things. In most cases, a string ought to be parsed to a DateTime
type.
2. Dates Do Not have a Format
I need to convert the string from dd/mm/yyyy to yyyy-MM-dd
No, you dont. Dates do not have a format. MSDN explains that a DateTime is simply a value:
Represents an instant in time, typically expressed as a date and time of day.
In the Remarks:
Time values are measured in 100-nanosecond units called ticks, and a particular date is the number of ticks since 12:00 midnight, January 1, 0001 A.D. (C.E.) in the GregorianCalendar calendar (excluding ticks that would be added by leap seconds). For example, a ticks value of 31241376000000000L represents the date, Friday, January 01, 0100 12:00:00 midnight.
Any format is just how that instant in time is expressed and displayed to humans - which usually involves changing the Date to a string - so it is strings/text and not Dates which have a format. Which means you only have to worry about a format when passing strings to the database (which should be avoided).
A date can be used in a query as a Datetime
type, most DBProviders are quite capable of passing the data and converting to however it is stored - that is its job. This assumes the db column is also a date type.
3. The Debugger uses Invariant Culture
When I debug it appears the date is still dd/mm/yyyy i.e. #6/15/2016 12:00:00 AM#
The VB IDE displays the date to you in the same format you must use when defining a date literal: dd/MM/yyyy
. This is meant to remove ambiguity and be consistent.
Dates do not have a format, so #6/4/1944#
is the same instant in time whether it is displayed that way or June 4, 1944
. Both have the same meaning.
4. Use SQL Parameters Always
Not only will this protect against SQL Injection attacks, it will make your code easier to read and prevent undesired type conversions.
Dim SQL = <sql>
Select ...
WHERE 1 = 1 And d.SurveyDate between @p1 AND @p2
AND #fld1 = @p3 AND #fld2 = @p4"
</sql>.Value
For a complex query, you can use an XML literal so you can format the query to make it more readable. There are no gyrations for ticks and string concatenation or continuation and no chance of accidentally converting a Date
or integer
to text with extra ticks where they are not needed.
You cannot use parameters for column names. So if you need to provide those, I would add them when the SQL is created, but you could also use String.Replace
:
' no idea what these are, probably need .ToString for Option Strict
SQL = SQL.Replace("#fld1", d.Field1).Replace("#fld2", d.Field3)
Then, provide the variables via parameters (this uses MySql):
Using cmd As New MySqlCommand(SQL, connection)
cmd.Parameters.Add("@p1", MySqlDbType.Date).Value = dtFrom.Date
cmd.Parameters.Add("@p2", MySqlDbType.Date).Value = dtTo.Date
cmd.Parameters.Add("@p3", MySqlDbType.Int32).Value = i
cmd.Parameters.Add("@p3", MySqlDbType.Int32).Value = j
...
End Using
Be sure to use the correct type as the xxxDbType
: Many DB provides have a Date
item which will pass only the date while DateTime
will include the time elements which is often not wanted in BETWEEN queries. Passing the date only (dtFrom.Date
) assures that as well.
You may want to read What do BETWEEN and the devil have in common? which explains why you may want to use a "dtTarget > @p1 AND dtTarget < @p2
" query rather than BETWEEN.