i heard people saying date time comparison do not work just due to time part because datetime has time part.
in sql i always compare datetime like this way and it works fine
select * from employee
where convert(varchar,dob,112) > '20111201' // this yyyymmdd format.
how could i simulate this in a LINQ query?
If you're using .NET 4 or above, just use the EntityFunctions.TruncateTime helper method. This will translate this type of datetime-to-date conversion to SQL for you.
from e in EfEmployeeContext
where EntityFunctions.TruncateTime(e.DOB) > new DateTime(2011,12,01);
The one thing to keep in mind is that operations on DateTime structs that represent database columns don't translate to SQL. So, you cannot write a query like:
from e in EfEmployeeContext
where e.DOB.Date > new DateTime(2011,12,01);
... because e.DOB represents the DOB column in the database, and EF won't know how to translate the Date sub-property.
However, there's an easy workaround depending on what dates you want:
If you want to include all employees that have a DOB on 12/01/2011 as well as those born after that date, then simply query:
from e in EfEmployeeContext
where e.DOB > new DateTime(2011,12,01);
If you want to include only employees born after 12/01/2011, then query:
from e in EfEmployeeContext
where e.DOB >= new DateTime(2011,12,02);
In short, the criteria, meaning a constant or literal DateTime you're comparing against, can be set up however you want. You just can't make radical modifications to properties that represent DB columns within the where predicate. That means you can't compare one DateTime column to a projection of another DateTime column, for instance:
//get all employees that were hired in the first six months of the year
from e in EfEmployeeContext
where e.HireDate < new DateTime(e.HireDate.Year, 7, 1);
Related
I am trying to return records for users based on their telephone numbers as well as a restriction to the PolicyEnd Field (DateTime Format) to return only those that are greater than or equal to 2022. However, I keep on running into several errors:
&& DateTime.ParseExact(s: ti0.Outer.Inner.PolicyEnd,format: "yyy-MM-dd",provider: __InvariantCulture_0) > DateTime.Now)' could not be translated.
var QUERY = from client in _ipacontext.Inclients
join policy in _ipacontext.Inpolicies on client.ClientId equals policy.AccountNo
join types in _ipacontext.InpolicyTypes on policy.PolicyType equals types.TypeId
where client.Telephone2 == "0000000" && DateTime.ParseExact(policy.PolicyEnd, "yyy-MM-dd", CultureInfo.InvariantCulture) > 2022
I have also tried this below but in vain :
where client.Telephone2 == "000000" && Convert.ToDateTime(policy.PolicyEnd).Year >=2022
An example of the Date Format is as below:
2022-08-31 00:00:00.000
Any help on other workarounds?
Dates have no format, they're binary types in all databases (except SQLite). SQL Server has date, datetime2, datetimeoffset, time and the legacy datetime for storing dates and time-of-day. Storing dates as strings in a string field is a critical bug that must be fixed. There's no way to control what goes into a string field, which means it's quite easy for garbage or strings with the wrong format to end up in the database.
Trying to parse such strings will result in bad performance and increased blocking even if indexes are used. Indexes are built using the stored values, not function results. Trying to parse PolicyEnd and filter by a specific date would have to scan the entire table, parse the values and only then decide which values to include. It will take Shared locks on the entire table while doing so, which would block any UPDATE or DELETE calls that tried to run at the same time, even if they were outside the date range.
If the field uses a date type, the PolicyEnd property should be a DateTime. In that casefiltering to find all dates after 2022 would be just :
var fromDate=new DateTime(2023,1,1);
var query = ....
where client.Telephone2 == "000000"
&& policy.PolicyEnd >=fromDate
This will result in a parameterized query that can use any indexes covering PolicyEnd to only touch policy rows whose PolicyEnd value matches the criteria.
The JOINs aren't necessary either. It's EF's job to generate the JOINs from the relations between entities. A Client should have a Policies collection. A Policy should have a PolicyType. A LINQ query that returns clients without a second phone whose policies end in the future should be :
var clients=from client in _context.Clients
from policy in client.Policies
where client.Telephone2 == "000000"
&& policy.PolicyEnd >=fromDate
select ...;
Since your db table column format datetime, just try to use function
var dt = new DateTime(2022,01,01);
....
&& EF.Functions.DateDiffYear(policy.PolicyEnd, dt) >= 0
or since you are checking only year you can try to use the whole data, sometimes it works
var dt = new DateTime(2021, 12, 31).AddDays(1).AddTicks(-1);
...
&& policy.PolicyEnd > dt
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.
I have the following LINQ to query the database and retreive deleted products from a particular date.
return _myDbEntities.Log
.Where(p => p.Action.Equals("Deleted") &&
(p.ActionDate > fromDate))
.Select(p => new DeletedProduct()
{
ProductId = p.ProductId,
ActionDate = p.ActionDate
}).ToList();
However, the query is retreiving values like product.ActionDate.Value = {12/8/2016 11:41:00 AM} when the fromDate was fromDate = {12/8/2016 11:41:00 AM}
The query clearly says GREATER THAN. What is happening here?
There are fractions of a second to each of your properties. Most likely, your record wasn't created at an exact second, whereas any user-created time would be set as such.
Another possibility is the difference between datetime and datetime2 in SQL Server.
The DateTime type stores time at much higher precision than seconds. They could be differing at millisecond or even tick (100 nanoseconds) level.
If you want to compare on a higher level, try this:
(p.ActionDate.Ticks / 10000000) > (fromDate.Ticks / 10000000)
Where 10000000 is the number of ticks in a second. Since the /is an integer division that does truncate the fraction, you turn ticks into full seconds.
UPDATE:
It seems like you are using entity framework. The comparison above will possibly not work there. The solution is to run your original query against the database, do a ToList and then filter the results again in a LINQ2Objects query using the logic above.
i need to get a difference of two dates ,one date from a table and one the current date, and the difference should be less than 9 0days. i need to use this as filter in where clause of the linq
i tried doing this
var list = from p in context.persons
where ((p.CreateDT).Subtract(DateTime.Now).Days < 90)
select p;
i get this excpetion :
LINQ to Entities does not recognize the method 'System.TimeSpan Subtract(System.DateTime)' method, and this method cannot be translated into a store expression.
I did research other articles but nothing helped..Any ideas
Trick here is that it can't translate all your fancy oo hoo-ha to plain old sql. Trick is to flip it on it's head:
var before = DateTime.Now.AddDays(-90);
var persons = context.Persons.Where(x => x.CreateDT > before);
EXPLANATION
Remember that everything in the WHERE bit of your LINQ statement must be translated from C# to SQL by the EF. It is very, very capable out of the box and handles most basic tasks, but it has no idea how to understand the most rudimentary method calls, such as DateTime.Subtract(). So the idea here is to let it do what it does best by precalculating a value and then passing that to the data tier.
The first line subtracts 90 days from the current time by adding negative 90 days. The second line passes it off to the database server.
The second line should translate to the SQL WHERE CreateDT > #BEFORETHIS
Update
It seems that EF doesn't support subtracting dates and returning a TimeSpan. Here's one way to solve the problem:
DateTime oldestDate = DateTime.Now.AddDays(-90);
var list = from p in context.persons
where p.CreateDT >= oldestDate
select p;
See this thread on Stackoverflow.
Try doing simply (p.CreateDate - DateTime.Now).Days < 90. Instead of calling DateTime.Subtract(). In some cases the operator overloads are implemented for Entity Framework even when the corresponding named methods are not.
If that doesn't work you could instead use ESQL or a stored procedure. As a final, dirty solution, you could call context.persons.ToList() and then call the DateTime.Subtract().
var islemList = (from isl in entities.Islemler where (isl.KayitTarihi.Date >= dbas && isl.KayitTarihi.Value.Date <= dbit) select isl);
It gives error: date is not supported in LINQ to Entities...
How can i get date in linq.
Use EntityFunctions.TruncateTime.
if KayitTarihi is a date column in DB (and dbas and dbit are DateTime), use:
var islemList = (from isl in entities.Islemler where (isl.KayitTarihi >= dbas && isl.KayitTarihi <= dbit) select isl);
The .Date property is not supported in Linq to Entities (though it may be supported in other implementations of Linq).
I realize that you only want to compare the dates, but there is no real problem with comparing the datetimes if the dbas and dbit values are datetimes with time 00:00:00.
You might have to offset the dates or use other inequality checks to get the proper interval but the comparison will work as you intend.
I would personally go with Jandek's solution.