Null exception being thrown by LINQ to EF - vb.net

This line of code is throwing an exception:
Dim z = (From r In t Where
(DateTime.ParseExact(r.appt_date, "yyyyMMdd", CultureInfo.CurrentCulture).Date.Month _
= myDate.Date.Month) And _
(DateTime.ParseExact(r.appt_date, "yyyyMMdd", CultureInfo.CurrentCulture).Date.Day = _
myDate.Date.Day) And _
(DateTime.ParseExact(r.appt_date, "yyyyMMdd", CultureInfo.CurrentCulture).Date.Year = _
myDate.Date.Year)).ToArray
T is defined as the following:
Dim t = (From p In mydb.C_MYTABLE Select p).ToArray
Since someone is going to ask what I'm trying to do... I have appointment dates stored as strings as yyyyMMdd in a DB, i can not change the DB. I need to be able to filter and sort them by date on the app level. Its my understanding that LINQ will not support conversions inside the query?

(This answer doesn't actually explain your NullReferenceException - but it gives an alternative approach.)
Given that you're checking for an exact date wouldn't it be easiest just to format myDate as yyyyMMdd before the query, and then have:
Dim z = (From r in t Where r.appt_date = formattedDate).ToArray
? That allows you to filter by a specific date - and if you need to filter to a range of dates, I'd expect that you could just use CompareTo. Your dates are in a sortable format, so if you need to find everything between (say) January 10th 2012 and September 20th 2013, you can just say that the string has to be "greater than or equal to" 20120110 and "less than or equal to" 20130920. You can also use this property for sorting - just ordering by the textual representation will be fine.
(That said, if there ever is a database redesign, please urge whoever's responsible to use a more appropriate data type!)

Enity framework its self will not support this. You can howerver select all of the rows out of the database and then sort them at the application level. Like so :
r
.ToList()
.Select(o => new
{
data = o,
appt_date = DateTime.ParseExact(r.appt_date, "yyyyMMdd", CultureInfo.CurrentCulture)
})
.Where(o => o.appt_date < DateTime.Now)
.OrderBy(o => o.appt_date);
This has a very big downside of selecting far to much out of the database.
Alternatively you could format your date into a string and use it to filter within the database and then parse the date:
var formatedDate = DateTime.now.ToString("yyyyMMdd");
r
.Where(o => o.appt_date == formatedDate)
.ToList()
.Select(o => new
{
data = o,
appt_date = DateTime.ParseExact(r.appt_date, "yyyyMMdd", CultureInfo.CurrentCulture)
})
.OrderBy(o => o.appt_date);
Ideally however I ask to improve the quality of the data. If you cant change the 'appt_date' to a Date type can you ask to insert a new column with the correct data type?

I need to be able to filter
You appear to be creating a non-sargable query.
I would suggest that instead of parsing the column you are querying on, create a variable that matches the value you are looking for.
dim myDate = DateTime.Now.ToString("yyyyMMdd");
Dim z = (From r In t Where
(r.appt_date = myDate)).ToArray
and sort them by date
The way the DB is storing the value should look like:
20120101 // Jan 01, 2012
20121231 // Dec 31, 2012
20130101 // Jan 01, 2013
20131231 // Dec 31, 2013
Natural string sorting will sort these in the correct order every time (asc, desc), so .OrderBy() and .OrderByDescending() will work as expected.

Related

Searching data by date - error

I'm using my VB.Net program to query a database in MS Access. In the database, I have a table that contain a "question_start" (Date/Time) field.
I would like to return the IDs of each record that occur on or after a date that I choose in my VB programme.
The data in the Access table, is being stored as Date/Time under a General Date format (e.g. '10/10/2016 15:48:01').
In VB.NEt, I am using the DateTimePicker object to select the date.
Below is the code I'm using to bring back all records that have a Start Date of 10/10/2016 (10th October 2016).
(Note 1: I have removed the time element from this particular search as I do not need my results to be time-sensitive here but are required later.)
Private Sub btnDateText_Click(sender As Object, e As EventArgs) Handles btnDateText.Click
Dim dt_QuestionDate As New DataTable()
dt_QuestionDate = getData("SELECT question_id
FROM tblQuestion
WHERE question_start => " & dtDateText.Value.ToString("dd-MM-yyyy") & ""
)
lstDateText.DataSource = dt_QuestionDate
lstDateText.DisplayMember = "question_id"
lstDateText.ValueMember = "question_id"
End Sub
**There are records in my database that should be returned, but I am receiving no values currently. I am not sure if it is how I've written the WHERE clause (I've done WHERE with "=>", ">=", and also "=") but I am not receiving records with the 10/10/2016.
Has anyone any ideas please? I don't know if it's because it's a simple mistake, or because of the time element that is stored in Access?
You need proper formatting of the string expression for the date value:
WHERE question_start => #" & dtDateText.Value.ToString("yyyy'/'MM'/'dd") & "#"

SQL Statement - Java

I've been trying to come up with a couple of SQL statements on how to get this right but no luck. I've tried between, >= and =<. Basically, the SQL statement that I've used is working but to an extent only.
My code works like this: the user will choose a date range (from date and to date) and the program will retrieve and show the data it has within those range. Like I said, it works but it also shows the days from the other months when what I want to show is just those particular days that the user picked. eg. from July 1, 2016 to July 5, 2016. What's happening is any month of the year that has those dates will show as well which makes that particular method a bit useless.
Any help or any explanation why is this so would be appreciated.
Below is my code:
stringFromDate = sdf.format(fromDate.getDate());
stringToDate = sdf.format(toDate.getDate());
String query = "Select * from tblSavings where date between '" + stringFromDate+ "' and '" + stringToDate+"'";
try{
pstmt = conn.prepareStatement(query);
rs = pstmt.executeQuery();
tblList.setModel(DbUtils.resultSetToTableModel(rs));
You can use SimpleDateFormat to get a string which is in proper format to be used as a date in SQLite, the proper format being yyyy-MM-dd:
String pattern = "yyyy-MM-dd";
SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
String stringFromDate = dateFormat.format(fromDate.getDate());
Seems like you're trying to re-invent the wheel here. PreparedStatements were created exactly for this usecase - setting variable values in a predefined structure. In your case, with the setDate method. From the context I'm guessing your fromDate and toDate variables are java.util.Date instances, so you'll have to convert them to java.sql.Dates
java.sql.Date fromDateToBind = new java.sql.Date(fromDate);
java.sql.Date toDateToBind = new java.sql.Date(toDate);
String query = "Select * from tblSavings where date between ? and ?";
try{
pstmt = conn.prepareStatement(query);
pstmt.setDate(1, fromDateToBind);
pstmt.setDate(2, toDateToBind);
rs = pstmt.executeQuery();
// use the results...
} // etc...

How to separate Date and time from DateTime method in ASP.Net

I am writing my SQL query to insert date and time and I want to separate date and time from DateTime method now. I want to store them in a table of my database separately. How I could insert them separately, please guide me.
Here is my incorrect query:
string CheckRequest = "select count(*) from Requests where Date='"+DateTime.Now.ToString()+"'";
DateTime variables in .NET are not 'separable' in date and time parts. They always contains the date and the time (hence the name). What you probably need is to query the database using only the Date part of your query. You could reach your result converting your DateTime variable to a string with just the date part using a special formatting pattern for the ToString method when applied to a DateTime variable
string CheckRequest = #"select count(*) from Requests
where Date='" +DateTime.Now.ToString("yyyy-MM-dd")+"';
but this still leaves an open problem.
Passing a formatted string requires that you format it exactly as your database expects it. Failing to accurately represent the string leads to a failure in retrieving records in the datatable.
A better approach is letting your database engine figure out the Date value from a DateTime variable using a parameterized query.
Something like this
string CheckRequest = #"select count(*) from Requests
where Date=#myDate"
using(SqlConnection cn = new SqlConnection(.......))
using(SqlCommand cmd = new SqlCommand(CheckRequest, cn))
{
cn.Open();
cmd.Parameters.Add("#myDate", SqlDbType.Date).Value = DateTime.Now.ToDay;
object result = cmd.ExecuteScalar();
if(result != null)
{
int count = Convert.ToInt32(result);
MessageBox.Show("Record found=" + count.ToString());
}
else
MessageBox.Show("No Record found");
}
Here I am using a parameter of type Date and assign the Now.ToDay (still a DateTime value but with the time equals to 12:00:00 AM) The database engine now knows to use only the Date part and query your table correctly

Checking for date overlap across multiple date range objects

I have several records in a database that have Start and End Dates
09/15/2011 - 09/30/2011
10/15/2011 - 10/22/2011
11/01/2011 - 11/15/2011
When user stores a record, I need to make sure dates don't overlap.
My simple code checks date ranges within a specific record (e.g. user enters 9/16/2011 or 10/21/2011, I throw an exception.)
But, on the slim chance a user gets creative (e.g. 10/14/2011 - 10/23/2011 or even 10/14/2011 to 11/16/2011), now they have circumvented my check.
BTW, the user could enter 10/14/2011 to 10/23/2011 if they were editing the record that contained values 10/15/2011 - 10/22/2011.
So, I'm trying to solve this riddle with a linq query. However, what I have isn't working exactly right.
UPDATE Nevermind about code not working. While trying to provide an example to expand on Miika's repsonse, I found my answer. So, giving credit to Miika for pointing me in the right direction and posting my working code below:
Here's my code:
Private Sub CheckForOverlap(myMonth As Messages.MyMonth)
Dim am As New MyMonth()
Dim amCollection As Messages.MyMonthCollection
Dim overlappingMyMonthDate As Boolean = False
Dim sErrorMsg As String = ""
'...non-applicable code omitted
Dim query = From s In amCollection _
Let s1 As MyMonth = CType(s, MyMonth) _
Where s1.AttendanceMonthID <> attendanceMonth.AttendanceMonthID And _
(CDate(attendanceMonth.StartDate) < CDate(s1.StartDate) And CDate(attendanceMonth.EndDate) > CDate(s1.EndDate)) _
Select s1
If query.Count > 0 Then
sErrorMsg = "Dates entered surround another entry"
End If
If overlappingMyMonthDate Then
Throw New Exception(sErrorMsg)
End If
End Sub
End Class
It all came down a LINQ query.
Do you need to do it in code or would SQL be an option? If the data is in a database, you could use the following query to check for overlaps.
SELECT COUNT(*)
FROM Table1
WHERE Table1.StartDate < 'endCheckDate'
AND Table1.EndDate > 'startCheckDate'
This will return a count of the number of overlaps found. 'endCheckDate' and 'startCheckDate' are your new query values (in date format). If your data is in a object collection in memory, then you could use LINQ. If you need help with a LINQ statement, let me know.

How to select only Date value No Time in LINQ to SQL?

I need to have a query which list all the user according to the date value in the database. Problems is this, in the database the date format is 5/5/2009 4:30:12 but I want to compare with 5/5/2009. I think the value of the based date is 5/5/2009 12:00:00 and that's why I couldn't query it.
The query is something like
dim db = new databcontext
dim user = from u in db.datacontext where u.signUpTime = 5/5/2009 select u.
May someone please check this problem.
Thanks in advance.
Your theory is correct. You should either use a range in your where clause:
u.SignupTime >= new DateTime(2009,5,5,0,0,0) AndAlso _
u.SignupTime < new DateTime(2009,5,6,0,0,0)
or check only the date:
u.SignupTime.Date = new DateTime(2009,5,5)