I have this LINQ query with Entity Framework 6:
var timeCapturesQuery = Context.TimeCaptures
.Where(t =>
&& t.StartDateTime.TimeOfDay < endTime
&& t.EndDateTime.TimeOfDay > startTime);
EndTime and StartTime are parmeters of type TimeSpan, StartDateTime and EndDateTime are columns on the table of datetime.
Unfortunately I get this error when it is run:
The specified type member 'TimeOfDay' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
How can I get a TimeSpan from a DateTime (i.e. the time from datetime in SQL) in this LINQ query?
Looks like DbFunctions.CreateTime is what you're looking for:
When used as part of a LINQ to Entities query, this method invokes the
canonical CreateTime EDM function to create a new TimeSpan object.
So to get results between two times, you can:
var timeCapturesQuery = Context.TimeCaptures.Where(t =>
DbFunctions.CreateTime(t.StartDateTime.Hour, t.StartDateTime.Minute, t.StartDateTime.Second) < endTime &&
DbFunctions.CreateTime(t.EndDateTime.Hour, t.EndDateTime.Minute, t.EndDateTime.Second) > startTime);
The property TimeOfDay does not supported in LINQ to Entities so you can try using SqlFunctions.DatePart method instead.
You should probably also convert your TimeSpans into DateTimes .
I think this should work (assuming the TimeSpans is from the begining of the day):
var now = DateTime.Now;
var today = new DateTime(now.Year, now.Month, now.Day);
var endDateTime = today + endTime;
var startDateTime = today + startTime
var timeCapturesQuery = Context.TimeCaptures.Where(t =>
SqlFunctions.DatePart("timeofday", t.StartDateTime) < SqlFunctions.DatePart("timeofday", endDateTime)
&& SqlFunctions.DatePart("timeofday", t.EndDateTime) > SqlFunctions.DatePart("timeofday", startDateTime));
Edit
As mentioned in the comments the specific property TimeOfTheDay is not supported in DatePart method.
Maybe EntityFunctions.DiffNanoseconds method will work:
var now = DateTime.Now;
var today = new DateTime(now.Year, now.Month, now.Day);
var endDateTime = today + endTime;
var startDateTime = today + startTime
var timeCapturesQuery = Context.TimeCaptures.Where(t =>
EntityFunctions.DiffNanoseconds(t.StartDateTime, endDateTime).Value < 0
&& EntityFunctions.DiffNanoseconds(t.EndDateTime, startDateTime).Value > 0);
Edit2
Another option which is much simpler and I think will work is just to compare the DateTimes.
We've already converted the TimeSpans into DateTimes and we can create a simple condition using LINQ to Entities and it should work because we are not using any of the DateTimes properties.
var now = DateTime.Now;
var today = new DateTime(now.Year, now.Month, now.Day);
var endDateTime = today + endTime;
var startDateTime = today + startTime
var timeCapturesQuery = Context.TimeCaptures.Where(t => t.StartDateTime < endDateTime && t.EndDateTime > startDateTime);
It looks like Linq2db supports it.
https://github.com/linq2db/linq2db/blob/1ff760181717c73859ab3a5519f76943241d460f/Source/Linq/Expressions.cs
Of course it is not very good option to use new ORM.
But I think it is most weak part of EF after performance.
So maybe it is good time to think again.
With Linq2db you can provide custom SQL logic (you need to create own expression). It was never necessary for me, but you can read this for more details.
Related
How to compare date without time in mongodb C# driver?
I try to use this code, bot it don't work.
MongoCursor<Log> query = _logCollection.FindAs<Log>(
Query.And(Query.EQ("Date.getDate()", date.Day),
Query.EQ("Date.getMonth()", date.Month),
Query.EQ("Date.getYear()", date.Year)));
Do you have any ideas?
Query for range of dates, which include your date:
var beginDate = date.Date; // e.g. 7/24/2013 00:00:00
var endDate = beginDate.AddDays(1); // e.g. 7/25/2013 00:00:00
var query = Query.And(Query<Log>.GTE(l => l.Date, beginDate), // including
Query<Log>.LT(l => l.Date, endDate)); // not including
var result = _logCollection.FindAs<Log>(query);
Same with LINQ (MongoDB.Driver.Linq namespace):
var result = from l in _logCollection.AsQueryable()
where l.Date >= beginDate && l.Date < endDate
select l;
I have a snapshot table in my database that holds historical data of appointment availability.
I'm trying to write a LINQ query to get the total number of AvailableSlots within a given date range from the latest snapshot.
Here is what my table looks like:
So with this given data, I'd want my LINQ query to return the sum of AvailableSlots within the date range of 2018-01-01 - 2018-01-02 and with the latest SnapShotTime. So, I'd expect the query to return 4.
Here is what I have so far.
var test = db.snapshots
.GroupBy(g =>
g.AppointmentTime >= startDate &&
g.AppointmentTime <= endDate
).Select(s => s.OrderByDesending(x => x.SnapShotTime).FirstOrDefault();
However, I'm not sure how to put the Sum of available slots into this LINQ query. Any help on writing this query would be appreciated!
i dont see exactly the query that you wrote do, but based on your explanation i think sth like this might have work
var query=db.snapshots
.Where(x=>x.AppointmentTime >= startDate &&
x.AppointmentTime <= endDate)
.GroupBy(x=>x.SnapShotTime)
.OrderByDesending(g=>g.Key)
.Take(1)
.Sum(x=>x.Value.AvailableSlots);
or if it seems so complicated you better first get the latest date like this
var latest=db.snapshots
.OrderByDesending(x => x.SnapShotTime)
.FirstOrDefault().SnapShotTime;
and then get your count like this
var query=db.snapshots
.Where(x=>x.AppointmentTime >= startDate &&
x.AppointmentTime <= endDate &&
x.SnapShotTime==latest)
.Sum(x=>x.AvailableSlots);
Here is what I did.
static void Main(string[] args)
{
DateTime startDate = new DateTime();
DateTime endDate = new DateTime();
List<FakeAppointments> appointmentsFromDatabase = new List<FakeAppointments>();
var appointmentsBetweenStartDateAndEndDate = appointmentsFromDatabase.Where(p => p.SnapshotTime >= startDate && p.SnapshotTime <= endDate).ToList();
int sum = appointmentsBetweenStartDateAndEndDate.Sum(p => p.AvailableSlots);
Console.ReadKey();
}
public class FakeAppointments
{
public DateTime SnapshotTime;
public int AvailableSlots;
}
My requirement is a simple one. I have some Mongo documents which contain a startTime (a DateTime field) and I want to query the containing collection for all of the documents that have a startTime on a particular day.
For example, I want all documents which have a date "22/10/2015", I don't care about the time component, I just want all documents that have that date.
I have written the following method to attempt to do this
public static async Task<List<uint>> DateRangeToEventIDAdapter(
MongoClient client, DateTime startDate, DateTime endDate, int? limit,
IProgress<string> progress, CancellationToken token)
{
if (startDate == endDate)
endDate = endDate.AddDays(1.0);
var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Gte(
MatchDetailsFields.START_TIME, BsonDateTime.Create(startDate.ToUniversalTime()));
filter = filterBuilder.And(filter, filterBuilder.Lte(MatchDetailsFields.START_TIME,
BsonDateTime.Create(endDate.ToUniversalTime())));
// Use Filter to get collection here...
}
[using C# Driver 2.0]. My problem case is when startDate == endDate, if I just use Eq. this returns zero records. So I attempt to add 24 hours to the time of the startDate for the endDate and then use .Lte and .Gte - this dow not work and returns both days.
This seems SOOOOO simple, but yet I can get Mongo to return what I want. What filter should I be using to retrieve all documents that occur on a specified day?
Thanks for your time.
This works for me (you should be using Lt and not Lte):
var theDay = new DateTime(2015,10,22).ToUniversalTime();
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Gte( "startTime" , theDay ) &
builder.Lt( "startTime", theDay.AddDays(1) ) ;
var list = await col.Find( filter ).ToListAsync();
You might code it as:
endDate = endDate.Date.AddDays(1);
How to compare date without time in mongodb C# driver?
I try to use this code, bot it don't work.
MongoCursor<Log> query = _logCollection.FindAs<Log>(
Query.And(Query.EQ("Date.getDate()", date.Day),
Query.EQ("Date.getMonth()", date.Month),
Query.EQ("Date.getYear()", date.Year)));
Do you have any ideas?
Query for range of dates, which include your date:
var beginDate = date.Date; // e.g. 7/24/2013 00:00:00
var endDate = beginDate.AddDays(1); // e.g. 7/25/2013 00:00:00
var query = Query.And(Query<Log>.GTE(l => l.Date, beginDate), // including
Query<Log>.LT(l => l.Date, endDate)); // not including
var result = _logCollection.FindAs<Log>(query);
Same with LINQ (MongoDB.Driver.Linq namespace):
var result = from l in _logCollection.AsQueryable()
where l.Date >= beginDate && l.Date < endDate
select l;
Please help.
I am trying to figure out how to use DATE or DATETIME for comparison in a linq query.
Example:
If I wanted all Employee names for those who started before today, I would do something like this in SQL:
SELECT EmployeeNameColumn
FROM EmployeeTable
WHERE StartDateColumn.Date <= GETDATE() //Today
But what about linq?
DateTime startDT = //Today
var EmployeeName =
from e in db.employee
where e.StartDateColumn <= startDT
The above WHERE doesn't work:
Exception Details: System.NotSupportedException: The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Use the class DbFunctions for trimming the time portion.
using System.Data.Entity;
var bla = (from log in context.Contacts
where DbFunctions.TruncateTime(log.ModifiedDate)
== DbFunctions.TruncateTime(today.Date)
select log).FirstOrDefault();
Source: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/
That should work. Are you sure that there isn't another part of the query that triggered the exception? I have several instances of queries of the form
var query = from e in db.MyTable
where e.AsOfDate <= DateTime.Now.Date
select e;
in my code.
It may be due to the date in the database being nullable. Try this:
var EmployeeName =
from e in db.employee
where e.StartDateColumn.Value <= startDT
You can check the condition like this
var nextDay = DateTime.Today.AddDays(1);
var query = from e in db.MyTable
where e.AsOfDate >= DateTime.Today && e.AsOfDate < nextDay
select e;
here you'll get the records on AsOfDate date as we checking between today(00:00:00) and tommorow(00:00:00) we'll get today's date record only what ever may be the time...
You can not use .Date
If you would like to check for today you can create a datetime with no time
DateTime myDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
var e = (from mds in myEntities.Table
where mds.CreateDateTime >= myDate
select mds).FirstOrDefault();
try this:
DateTime dd = DateTime.Parse("08/13/2010 00:00:00");
var data = from n in ContributionEligibilities
where n.ModifiedDateTime.Date >= DateTime.Parse("08/13/2010").Date
select n;
data.Dump("Result") ;
I'm curious to the error message saying 'Date', when you're passing a 'DateTime'. Could it be that 'StartDateColumn' is actually a 'Date', rather than a 'DateTime' in the database? That might mess up the comparison...
use a local variable to store the Date value and then use that variable in the query:
DateTime today = DateTime.Now.Date;
from scheme in context.schemes
where scheme.EndDate > today
select scheme
I am using a LinqDataSource and I had problems getting my query with a Date Comparison in it to execute without errors. The answer is to use the WhereAddParameters function and add the test value as a strongly typed parameter.
See the example below where I am matching a groupid and checking to see if the StopDate in my record is greater that or equal to a Date/Time stamp of now.
I am using this code fragment currently and it works like a charm.
LinqCampaigns.WhereParameters.Add("StopDate", System.Data.DbType.Date, DateTime.Now.ToString())
LinqCampaigns.Where = "GroupId = " & myGrp & " && " & "StopDate >= #StopDate"
Works like a charm....
.Date did not work, but .Day did for me.
var query = from o in Payments
where o.Order.OrderDate.Day != o.PaymentDate.Day
orderby o.Order.OrderDate
select new
{
o.Order.OrderID,
o.Order.OrderDate,
o.PaymentDate,
o.Order.FirstName,
o.Order.LastName,
o.Order.CustomerID
};
query.Dump();
ensure that you check null value like this :
'(from mm in _db.Calls
where mm.Professionnal.ID.Equals(proid)
&& mm.ComposedDate.HasValue &&
(mm.ComposedDate.Value >= datemin) && (mm.ComposedDate.Value <= date)
select mm).ToArray();'