Linq to SQL DateTime2 query - c#

I have a table with a datetime2 field and I need to get all rows out of it where the date is today. Rather oddly (in my opinion but I'm sure there's a valid reason for it) if I do:
MyTable.Where(t => t.Date == DateTime.Today).ToList()
it returns nothing even though there are entires with todays date.
What am I missing here? I thought that datetime2 allowed you to query like this instead of having to use greater than and less than to specify a timeframe?
Edit
I've tried using the .Date portion of the DateTime2 representation in Linq to SQL:
MyTable.Where(t => t.Date.Date == DateTime.Today).ToList()
but I'm still getting nothing. Yet in my database there are rows with the value 2011-08-05 00:00:00.0000000 which is clearly today.
Edit again
I've ran the query:
List<string> dates = MyTable.Select(t => t.Date.Date.ToString()).ToList();
and I'm getting results like 2011-08-05, so that portion obviously works.
However, when I run
DateTime.Today.Date.ToString()
I get 08/05/2011 00:00:00. Could the addition of this time portion be causing the issue? How would I remove this?
Edit 3
Got it to work using the code:
MyTable.Where(t => t.Date.Date.ToString() == DateTime.Today.Date.ToString("yyyy-dd-MM")).ToList();
This seems hacky though (converting to a string before comparison) and surely there must be a cleaner way?

It sounds like the date in the database isn't actually today (8th May). It's probably 5th August.

It looks like your datetime2 field is called Date. You need to use the Date property of this Date field to ignore the time of day.
MyTable.Where(t => t.Date.Date == DateTime.Today).ToList()

Related

DocumentClient takes too long when queried over a DateTime field

I have the following code to get the list of some objects from a DocumentDB database:
var document = this._client.CreateDocumentQuery<T>(UriFactory.CreateCollectionUri(dbName, collectionName), queryOptions)
.Where(r => r.pDate >= startDate && r.pDate <= endDate);
var result = document.ToList();
pDate is of type DateTime, and stored in the database as string with ISO8601 format.
The query takes unreasonably too long, like 4 to 5 minutes, to return the results back. When I trace the program it is that .ToList() where the program gets stuck. Oddly, the query quickly returns for some specific start and end dates.
The query also quickly comes back with some results if I put the filter on some fields other than pDate.
My settings are consistent with explanations in this document but I still get a very poor performance almost all the time except for those few exceptions.
I have tried several methods mentioned here and there to resolve the issue, but no luck so far. I appreciate any comment or solution to the problem.
It could be because the indexing that is applied on this particular field.
From this link
https://learn.microsoft.com/en-us/azure/cosmos-db/indexing-policies,
you would need an Range index for range or Order by Queries.
The default index policy that is applied to a collection is
"Hash for Strings and Range for Numbers"
Datetimes are stored as strings, so for running range comparison queries or order by queries you would need to set the indexing policy to "Range" for string datatypes with precision to -1.

"Where" clause in linq to sql query using DateTime?

I'm trying to run a query of a table with the columns Domain, LastUsed, and FreqInHours In c#.
I just want to return all the Domains that I need to crawl.I find this out by checking the datetime that they were last Crawled (LastUsed) and how frequently they should be crawled (ex. every 6 hours). If the current date/time - the time it was last crawled is greater than the frequency I add want to return that domain.
Here is the current query I've written:
var query = (from c in context.SitemapFreqs
where (DateTime.Now - c.LastUsed).TotalHours > c.Freq
select c.domain);
Here is the exception I'm being given:
LINQ to Entities does not recognize the method 'System.DateTime ?
ToDateTime(System.Object)' method, and this method cannot be translated into a store expression.
Any help would be really appreciated.
You can use DbFunctions class and method DiffHours.
Here is an example:
var query = (from c in context.SitemapFreqs
where DbFunctions.DiffHours(DateTime.Now,c.LastUsed) > c.Freq
select c.domain);
Here is the documentation. Hope it helps.
Complex DateTime stuff is a bit much for Linq2SQL to handle.
If it's a relatively small amount of data, load it all into memory first:
var query = (from c in context.SitemapFreqs.ToList()
where (DateTime.Now - c.LastUsed).TotalHours > c.Freq
select c.domain);
If it's a larger amount of data, you can use DbFunctions, or provide the query yourself.
context.SitemapFreqs.SqlQuery("SELECT * from SitemapFreqs WHERE DATEDIFF('hour', GETDATE(), LastUsed) > Freq")
If you make sure the query returns the columns the SitemapFreqs object expects, it will map the objects just like it would anything else.
Looks like your c.LastUsed property is nullable. You can subtract nullable DateTimes using the c.LastUsed.Value property, but you should know that if it is null, this will throw an exception as you can't subtract a DateTime - null. I believe you have two options:
Change the property LastUsed in your class to a non-nullable DateTime by removing the ?.
Create a method inside of your class that determines if the DateTime? LastUsed is equal to null. If it is, return something where your LINQ query will ignore that value. (I.E: Set the value of LastUsed = DateTime.Now so that your LINQ query comes back as 0).
Hope this helps.

DevForce 2010 Formatting Dates for EntityQuery

I've run into a situation where I need to query by Date and Time. I'm trying to write an EntityQuery where the date and time are in the same format. The query below returns no rows. However if I remove the two date clauses, rows are returned and then I can check the dates looping through the results. I would prefer to use the dates in the query.
the variable ap in the query is a C# object
var query = from log in Manager.Logs
where log.StartDttm == ap.StartDttm
&& log.EndDttm == ap.EndDttm
&& log.TypeId == 1
select log;
I came up with this workaround to query between midnight and 11:59:59pm for each date. I don't like this either, but this does at least reduce the number of rows returned by the query.
var query = from log in Manager.Logs
where && log.StartDttm >= ap.StartDttmQueryBegin
&& log.StartDttm <= ap.StartDttmQueryEnd
&& log.EndDttm >= ap.EndDttmQueryBegin
&& log.EndDttm <= ap.EndDttmQueryEnd
&& log.TypeId == 1
select log;
DevForce doesn't expect any specific date/time formats or modify them when the query is built and executed, but it's not the date format per se but the precision of the data stored in the database vs. the precision of the DateTime fields in the "ap" object which is causing the issue.
In EF you can use the EntityFunctions and/or SQLFunctions APIs to perform date/time truncating/formatting, but these are difficult to use in DevForce due to the client/server serialization and EntityQuery to ObjectQuery conversion that DevForce performs. These APIs can be made to work on the "server side" of DevForce via an RPC call.
Your workaround, although it may feel cumbersome, is probably your best option. You could also try calling a stored procedure or using an ESQL passthru query, both of which will give you a little more control over the resulting SQL query.

How to convert string to datetime and then get the lowest date

Records are coming from database and date is in the string format. I am using LINQ Min() query to select the record with lowest date. LINQ is not allowing me to use Convert.ToDateTime().
How can I get lowest date record?
You could do something like
.Min(ob => System.Convert.ToDateTime(ob.DateProperty));
This way the value gets converted before checking for the lowest value.
What do you mean by "linq is not allowing me Convert.ToDateTime()" ?
Can you not do:
DateTime minDate = listOfStrings.Select(x => Convert.ToDateTime(x)).Min();
..?
If the strings are not in a date/time format that is handled by Convert.ToDateTime(), you may need to look into DateTime.ParseExact() with an appropriate format string.
Edit: sorry, just realized another possibility. Do you mean that you cannot do the Convert.ToDateTime() because you are using LINQ against SQL and it is not usable within the expression? If so, try:
DateTime minDate = listOfStrings.ToList().Select(x => Convert.ToDateTime(x)).Min();
.. with a ToList() to force it to perform the query and then to the conversion.
there's a way of doing it by using the Orderby method in your LINQ request,
using a Func() on the (datetime)field you wish to order by, then selecting the first element.
It's not very clean as i would use a datetime in the database, but it should work.
Looking into some code samples would be useful. But this might help.
var minDateTime = strings.Min(s => DateTime.Parse(s));

Compare date if there is a date in the database

I have a simple LINQ query. I would like to only check the DateDisable if there is an entry in the database. If the user doesn't select a date to disable the entry will always show. Can someone please show me how to add a conditional statement within linq
return (from promo in context.Promoes
where promo.DateEnable <= DateTime.Today
where promo.DateDisable >= DateTime.Today
orderby promo.SortOrder
select promo).ToList();
Given that DateEnable is a DateTime?, you can do the following:
// Get today.
DateTime today = DateTime.Today;
return (
from promo in context.Promoes
where
promo.DateEnable <= today &&
(promo.DateDisable == null || promo.DateDisable >= today)
orderby promo.SortOrder
select promo
).ToList();
Basically, you need to check for null or whether or not the date is greater than today.
Also you should capture the value outside of the statement, it's not guaranteed that the the LINQ provider will translate DateTime.Today on the database side correctly.
However, be warned that because of deferred execution, if you wait a long time to execute the query, today might not give you the value you expect (if the time between declaring the query and executing it rolls past midnight).
Of course, if your database server is in a different timezone than your application server, then you'll need to ensure that DateTime.Today is handled by your LINQ provider correctly (so that it's executed on the server) and use that if you want to compare against time on the DB server. If your provider doesn't handle translating DateTime.Today correctly, then you'll have to resort to a stored procedure and call that.

Categories