compare the dates with linq - linq

I have this code:
i.SpesaVitto = db.TDP_NotaSpeseSezB.Where(p => p.GiornoFine == null &&
((DateTime)p.Giorno).Date == ((DateTime)i.Data).Date &&
p.MissioneID == missioneID).Sum(p => p.Costo);
If i launch it i obtain this error:
The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
how can i compare the datetimes field without the hours part
thanks

Well this is certainly not the most efficient way to do it, but you can try something like:
i.SpesaVitto = db.TDP_NotaSpeseSezB.Where(p => p.GiornoFine == null &&
(new DateTime((p.Giorno as DateTime).Year, (p.Giorno as DateTime).Month, (p.Giorno as DateTime).Day) == (new DateTime((i.Data as DateTime).Year, (i.Data as DateTime).Month, (i.Data as DateTime).Day) &&
p.MissioneID == missioneID).Sum(p => p.Costo);
Depending on the requirements I would probably implement something cleaner and faster but it would depend on how the dates are stored in your database.

Check out this question it looks like the syntax error may be in your SQL, not in your LINQ. The asker in that question had written:
SQL ------
Select
EmployeeNameColumn
From
EmployeeTable
WHERE StartDateColumn.Date <= GETDATE() //Today
SQL ------
When they should have written:
SQL ------
Select
EmployeeNameColumn
From
EmployeeTable
WHERE StartDateColumn <= GETDATE() //Today
SQL -

solution for your problem will be the "SqlFunctions class and DateDiff" http://msdn.microsoft.com/en-us/library/system.data.objects.sqlclient.sqlfunctions.aspx

Related

Linq DateTime comparison not working

I have the following code:
DateTime timeStamp = Convert.ToDateTime(Request.QueryString["TimeStamp"]);
var result = (from rs in db.VRec
where
rs.TimeStamp == timeStamp &&
rs.Fixure == wFixture
select rs).ToList();
The result shows 0 even though the correct timeStamp is passed.
If I remove the part where I do the TimeStamp comparison:
rs.TimeStamp == timeStamp
The code works fine.
Any idea on why the datetime comparison may not be working?
DateTime has a pretty fine resolution - likely you are comparing timestamps that only differ in milliseconds, which will fail. You probably want something like:
DateTime now = DateTime.Now;
DateTime then = now.Add(TimeSpan.FromMilliseconds(1));
const int EPSILON_MS = 10;
if(now.Subtract(then).TotalMilliseconds < EPSILON_MS)
{
Console.WriteLine("More or less equal!");
}
Linq converts DateTime arguments to DateTime2 in the sql query executed.
That is, when you do the comparison the actual sql executed will compare a DateTime to a DateTime2. This comparison will "cast" the DateTime to a DateTime2 and the millisecond part will be expanded to a greater resolution (in an odd way in my opinion, please enlighten me).
Try to execute the following sql:
declare #d1 datetime = '2016-08-24 06:53:01.383'
declare #d2 datetime2 = '2016-08-24 06:53:01.383'
declare #d3 datetime2 = #d1
select #d1 as 'd1', #d2 'd2', #d3 'converted'
select (case when (#d1 = #d2) then 'True' else 'False' end) as 'Equal',
(case when (#d1 > #d2) then 'True' else 'False' end) as 'd1 greatest'
From the question, I do not know if you want to compare the date with time or only the date part. If you only want to compare date then following would work
var result = (from rs in db.VRec
where
rs.TimeStamp.Date == timeStamp.Date &&
rs.Fixure == wFixture
select rs).ToList();
Since you are using some reference to db, it gives me a feeling that you are fetching your records from database (which ORM you are using is not obvious from the question or tags). Assuming that you are using Entity framework the above query will fail with exception that .Date has no direct translation to sql. If so you can rewrite the query as following to make it work.
var result = (from rs in db.VRec
where
rs.TimeStamp.Day == timeStamp.Day &&
rs.TimeStamp.Month == timeStamp.Month &&
rs.TimeStamp.Year == timeStamp.Year &&
rs.Fixure == wFixture
select rs).ToList();
The benefit of this approach is that you can compare properties to arbitrary deep level i.e you can compare Hours, Minutes,Seconds etc. in your query. The second query is tested in Entity framework 5.

The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties

Using this code in Entity Framework I receive the following error. I need to get all the rows for a specific date, DateTimeStart is of type DataType in this format 2013-01-30 12:00:00.000
Code:
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => x.DateTimeStart.Date == currentDateTime.Date);
Error:
base {System.SystemException} = {"The specified type member 'Date' is
not supported in LINQ to Entities. Only initializers, entity members,
and entity navigation properties are supported."}
Any ideas how to fix it?
DateTime.Date cannot be converted to SQL. Use EntityFunctions.TruncateTime method to get date part.
var eventsCustom = eventCustomRepository
.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => EntityFunctions.TruncateTime(x.DateTimeStart) == currentDate.Date);
UPDATE: As #shankbond mentioned in comments, in Entity Framework 6 EntityFunctions is obsolete, and you should use DbFunctions class, which is shipped with Entity Framework.
You should now use DbFunctions.TruncateTime
var anyCalls = _db.CallLogs.Where(r => DbFunctions.TruncateTime(r.DateTime) == callDateTime.Date).ToList();
EntityFunctions is obsolete. Consider using DbFunctions instead.
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => DbFunctions.TruncateTime(x.DateTimeStart) == currentDate.Date);
I would like to add a solution, that have helpt me to solve this problem in entity framework:
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => x.DateTimeStart.Year == currentDateTime.Year &&
x.DateTimeStart.Month== currentDateTime.Month &&
x.DateTimeStart.Day == currentDateTime.Day
);
I hope that it helps.
Always use EntityFunctions.TruncateTime() for both x.DateTimeStart and currentDate.
such as :
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference).Where(x => EntityFunctions.TruncateTime(x.DateTimeStart) == EntityFunctions.TruncateTime(currentDate));
Just use simple properties.
var tomorrow = currentDateTime.Date + 1;
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference)
.Where(x => x.DateTimeStart >= currentDateTime.Date
and x.DateTimeStart < tomorrow);
If future dates are not possible in your app, then >= x.DateTimeStart >= currentDateTime.Date is sufficient.
if you have more complex date comparisons, then check Canonical functions
and if you have EF6+ DB functions
More Generally - For people searching for issues Supported Linq methods in EF
can explain similar issues with linq statements that work on Memory base Lists but not in EF.
Simplified:
DateTime time = System.DateTime.Now;
ModelName m = context.TableName.Where(x=> DbFunctions.TruncateTime(x.Date) == time.Date)).FirstOrDefault();
Use the bellow code for using EF6:
(DbFunctions.TruncateTime(x.User.LeaveDate.Value)
I have the same issue with Entity Framework 6.1.3
But with different scenario. My model property is of type nullable DateTime
DateTime? CreatedDate { get; set; }
So I need to query on today's date to check all the record, so this what works for me. Which means I need to truncate both records to get the proper query on DbContext:
Where(w => DbFunctions.TruncateTime(w.CreatedDate) == DbFunctions.TruncateTime(DateTime.Now);
Another solution could be:
var eventsCustom = eventCustomRepository.FindAllEventsCustomByUniqueStudentReference(userDevice.UniqueStudentReference).AsEnumerable()
.Where(x => x.DateTimeStart.Date == currentDate.Date).AsQueryable();
I've faced this same issue and it seems that it is really caused by the presence of a call to the .Date property within the Where method. When removed, the error disappears. Consider that calling the .Date property on any side of the comparison operator causes this error. Calling the .Date property outside and before the Where method is enough to solve this error.

Entity Framework: Best way to query for a set of dates using Linq

I have a set of unique DateTimes (without time portion) that the user can select from the user interface. This is not only a range like "LastWeek" or "LastMonth". The user can selcet every single day he wants.
What might be the best way to Linq-query in EntityFramework for matching results? I have a table Foo with an Attribute CreatedAt, which stores information with time portion. Of course I dont want to check the CreatedAt-Property on client side, SqlServer should do the job for me.
I think it should be someting like:
var query = _entities.Foo.Where(x => x.UserID == user.ID);
if (selectedDates.IsNullOrEmpty() == false)
query = query.Where(x => x.CreatedAt 'IsIn' selectedDates);
or:
foreach (var date in selectedDates)
query = query.Where(x => x.CreatedAt.Year == date.Year && x.Month == date.Month && x.Day == date.Month) //but of course here I have the problem that I have to use the 'Or'-Operator, not 'And'.
How can I accomplish this?
You can use EntityFunctions.TruncateTime() to perform a truncation of the date on the server. Then something along the lines of this should work.
query = query.Where(x => selectedDates.Contains(EntityFunctions.TruncateTime(x));
You can call the Contains extension method on selectedDates. Entity Framework 4.0 will understand this and will translate it to an IN operator in SQL:
if (selectedDates.IsNullOrEmpty() == false)
query = query.Where(x => selectedDates.Contains(x.CreatedAt));
Try query = query.Where(x => selectedDates.Contains(x.CreatedAt));

DateTime and LinqToEntities

I have DateTime field, which storing date + time. I need to use only date part, so I try:
query = query.Where(p => p.CreatedDateTime.Date == DateStart);
but I get the following error:
The specified type member 'Date' is not supported in LINQ to Entities.
Only initializers, entity members, and entity navigation properties
are supported.
why and how to fix it?
what about this:
query = query.Where(p => EntityFunctions.TruncateTime(p.CreatedDateTime) == DateStart);
You cannot use extension functions in LINQ queries that result in a database hit if Entity Framework has no way to convert this into valid SQL.
There may be a more compact solution but the following should work fine:
query = query.Where(p =>
p.CreatedDateTime.Year == DateStart.Year &&
p.CreatedDateTime.Month == DateStart.Month &&
p.CreatedDateTime.Day == DateStart.Day);

How to convert a LINQ query from query syntax to query method

Linq and EF4.
I have this Linq query in query syntax I would like convert into query method.
Are you able to do it? I tried more tha 2 hours without success :-(
Thanks for your time
CmsContent myContentObj = (from cnt in context.CmsContents
from categoy in cnt.CmsCategories
where categoy.CategoryId == myCurrentCategoryId && cnt.ContentId == myCurrentContentId
select cnt).Single();
My original answer selected the wrong item. It's a bit more complicated than what I had (which Ani has posted). Here's what I believe is an equivalent query however and should perform better:
CmsContent myContentObj =
context.CmsContents
.Where(cnt => cnt.ContentId == myCurrentId
&& cnt.CmsCategories
.Any(categoy => categoy.CategoryId == myCurrentCategoryId))
.Single();
Here is a non-direct translation that I believe performs the same task in much less code:
var myContentObj = context.CmsContents.Single(
x => x.ContentId == myCurrentContentId &&
x.CmsCategories.Any(y => y.CategoryId == myCurrentCategoryId)
);
Here's how the C# compiler actually does it, with some help from .NET Reflector to verify:
var myContentObj = context
.CmsContents
.SelectMany(cnt => cnt.CmsCategories,
(cnt, categoy) => new { cnt, categoy })
.Where(a => a.categoy.CategoryId == myCurrentCategoryId
&& a.cnt.ContentId == myCurrentContentId)
.Select(a => a.cnt)
.Single();
Essentially, the 'nested' from clauses results in a SelectMany call with a transparent identifier (an anonymous-type instance holding the 'parent' cnt and the 'child' categoy). The Where filter is applied on the anonymous-type instance, and then we do another Select projection to get back the 'parent'. The Single call was always 'outside' the query expression of course, so it should be obvious how that fits in.
For more information, I suggest reading Jon Skeet's article How query expressions work.

Resources