I'm trying to compare dates using Linq to Entities on a SQLite database. The following code works, but I need to trim off the time portion to get the correct results.
return (from c in Context.Car
join d in Context.Driver on c.CarID equals d.DriverID
join r in Context.Rides on c.CarID equals r.RideID into rideJoin
from rides in rideJoin.DefaultIfEmpty()
where c.IsActive && d.IsActive
group rides by new { c.CarID, d.FullName, d.HireDate, d.FirstPayRiseDate } into grp
select new MyCustomClass
{
CarID = grp.Key.CarID,
Driver = grp.Key.FullName,
NumberOfRides = grp.Count(x => x != null && x.RideDate >= grp.Key.HireDate && x.RideDate <= grp.Key.FirstPayRiseDate)
}).OrderBy(x => x.Driver ).ToList();
I've tried using System.Data.Entity.DBFunctions like so and I get this error:
NumberOfRides = grp.Count(x => x != null && DbFunctions.TruncateTime(x.RideDate) >= grp.Key.HireDate && DbFunctions.TruncateTime(x.RideDate) <= grp.Key.FirstPayRiseDate)
SQL logic error or missing database no such function: TruncateTime
I also get the same error with DBFunctions.DiffDays()
I've also tried casting to Date like so and get this error:
NumberOfRides = grp.Count(x => x != null && x.RideDate.Date >= grp.Key.HireDate && x.RideDate.Date <= grp.Key.FirstPayRiseDate)
'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported
What gives? How am I supposed to do Date functions in Linq to Entities with SQLite??
I need to trim off the time portion to get the correct results
No you don't. If you want to include the rows from startDate through endDate inclusive then just use
... && x.RideDate >= startDate && x.RideDate < endDate.AddDays(1)
(Note that the second comparison is now "strictly less than".)
How are you storing dates on the database ? as unix time integrs ?
in that acse you can amend your connection string to include this following config setting and it will make it easy to read the datetime value via EF.
datetimeformat=UnixEpoch;datetimekind=Utc
So something like :
data source="|DataDirectory|\data.sqlite";datetimeformat=UnixEpoch;datetimekind=Utc
Ref: https://stackoverflow.com/a/24323591/3660930
Related
I have this LINQ Where clause that is declaring 2 variables on the SQL query
var parkingLotPrice =
_context.ParkingLotPrice
.Where(x => currentDate >= x.EffectiveDate && (currentDate <= x.ExpiryDate || x.ExpiryDate == null))
.ToQueryString();
It generates this SQL Query:
DECLARE #__currentDate_0 datetime2 = '2021-07-21T17:48:29.1106534-06:00';
DECLARE #__currentDate_1 datetime2 = '2021-07-21T17:48:29.1106534-06:00';
SELECT [p].[ParkingLotId],
[p].[PriceScheduleId],
[p].[EffectiveDate],
[p].[ExpiryDate]
FROM [ParkingLotPrice] AS [p]
WHERE (#__currentDate_0 >= [p].[EffectiveDate]) AND ((#__currentDate_1 <= [p].[ExpiryDate]) OR [p].[ExpiryDate] IS NULL)
Note: the declarations contains the same value.
The problem is the (currentDate <= x.ExpiryDate || x.ExpiryDate == null).
If I remove the null evaluation, it only declares 1 variable.
DECLARE #__currentDate_0 datetime2 = '2021-07-21T17:32:31.3980763-06:00';
SELECT [p].[ParkingLotId],
[p].[PriceScheduleId],
[p].[EffectiveDate],
[p].[ExpiryDate]
FROM [ParkingLotPrice] AS [p]
WHERE (#__currentDate_0 >= [p].[EffectiveDate]) AND (#__currentDate_0 <= [p].[ExpiryDate])
Is there a way of keeping the Where evaluation, but only declare 1 variable?
And what is wrong with it? Does it return a wrong result? I created hundreds queries with null and without and they always returned the right result.
I can see the real problem in your query. The way you compare dates. It will compare times too. In some cases it will return a wrong result. I highly recommend you to compare only dates
var parkingLotPrice = _context.ParkingLotPrice
.Where(x => EF.Functions.DateDiffDay(x.EffectiveDate,currentDate) >=0
&& (x.ExpiryDate == null || EF.Functions.DateDiffDay(currentDate,x.ExpiryDate)>=0 )).ToList();
or if you need some time try this
var parkingLotPrice = _context.ParkingLotPrice
.Where(x => EF.Functions.DateDiffMinute(x.EffectiveDate,currentDate) >=0
&& (x.ExpiryDate == null || EF.Functions.DateDiffMinute(currentDate,x.ExpiryDate)>=0 )).ToList();
I'm trying to select nullable datetime by adding days.
As instance
COMPLETE_TIME = (x.VISIT_DATE.HasValue ? x.VISIT_DATE.Value.AddDays(1) : (DateTime?)null)
If datetime has value i want to add 1 days by selecting query as above.
If datetime does not have value i want to set nullable datetime by selecting query as above.
However if i try above code i get Error (please check bottom side for error)
All Query:
var result=
(from s in context.SURVEYs
join x in context.SURVEY_X on s.SURVEY_ID equals x.SURVEY_ID
join sas in context.SURVEY_ANSWER_SELECTION on s.SURVEY_ID equals sas.SURVEY_ID
join o in context.REP_OPTION on sas.OPTION_ID equals o.OPTION_ID
from PCO in context.REP_PARENT_CHILD_OPTIONS.Where(w => w.CHILD_OPTION_ID == sas.OPTION_ID).DefaultIfEmpty()
where
(s.SURVEY_ID == 5 || s.PARENT_SURVEY_ID == 5) &&
o.SUGGESTION != null &&
PCO.PARENT_OPTION_ID == null
select new
{
SUGGESTION = o.SUGGESTION,
DISPLAY_ORDER = "0",
SUGGESTION_TYPE = o.SUGGESTION_TYPE,
o.EXAMPLE_IMAGE_ID,
COMPLETE_TIME = (x.VISIT_DATE.HasValue ? x.VISIT_DATE.Value.AddDays(1) : (DateTime?)null) // Problem in this part
}).ToList();
Error:
An exception of type 'System.NotSupportedException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
Question:
How can i select added datetime or null datetime in select part ?
Any help will be appreciated.
Thanks.
If you are using EF 6 you could use on of the DbFunctions
var result=
(from s in context.SURVEYs
join x in context.SURVEY_X on s.SURVEY_ID equals x.SURVEY_ID
join sas in context.SURVEY_ANSWER_SELECTION on s.SURVEY_ID equals sas.SURVEY_ID
join o in context.REP_OPTION on sas.OPTION_ID equals o.OPTION_ID
from PCO in context.REP_PARENT_CHILD_OPTIONS.Where(w => w.CHILD_OPTION_ID == sas.OPTION_ID).DefaultIfEmpty()
where
(s.SURVEY_ID == 5 || s.PARENT_SURVEY_ID == 5) &&
o.SUGGESTION != null &&
PCO.PARENT_OPTION_ID == null
select new
{
SUGGESTION = o.SUGGESTION,
DISPLAY_ORDER = "0",
SUGGESTION_TYPE = o.SUGGESTION_TYPE,
o.EXAMPLE_IMAGE_ID,
COMPLETE_TIME = (x.VISIT_DATE.HasValue ? Dbfunctions.AddDays(x.VISIT_DATE.value, 1) : (DateTime?)null) // Problem in this part
}).ToList();
var MyCours = Db.COURS.Where(C => C.CLASSE_ID == ClassID
&& DateTime.Now>= C.START_DATE
&& DateTime.Now <= C.END_DATE)
.ToList();
Some change still dont work !
A likely problem is that the provider can't project DateTime.Compare into a SQL statement. There is potentially also a logical error in the direction of comparison (unless you really want enddate < now < startdate), and I would also suggest using .ToList() to materialize into a list:
var theTimeNow = DateTime.Now;
var MyCours = Db.COURS.Where(C => C.CLASSE_ID == ClassID
&& theTimeNow >= C.START_DATE
&& theTimeNow <= C.END_DATE)
.ToList();
Projecting DateTime.Now into a variable isolates the non-determinism of it, i.e. to ensure that both comparisons are against the same time.
I want my query to stop displaying time and just the date. This is what I've tried to far:
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo
&& z.ActivityDate >= EndDateTo
&& z.Indepth == false
select new
{
Date = new DateTime(z.ActivityDate.Year, z.ActivityDate.Month, z.ActivityDate.Day),
Subject = z.Subject
}).ToList();
And
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo
&& z.ActivityDate >= EndDateTo
&& z.Indepth == false
select new
{
Date = z.ActivityDate.Date,
Subject = z.Subject
}).ToList();
And both didn't work.
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression. when trying to apply a string method.
You can use anyDate.ToString("ddMMyyyy");//any preferred format.
Not sure if that is what you are looking for!
Your queries return objects with Date & Subject properties.
In the Date property you are passing a DateTime object. In order to display the short date you have a "ToShortDateString()" function on a date.
If you dont want to work with a date and prefer selecting a string, then do the conversion inside the linq query.
Use this if you want to return strings:
var q = (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo && z.ActivityDate >= EndDateTo && z.Indepth == false
select new { Date = z.ActivityDate.Date.ToShortDateString(), Subject = z.Subject }).ToList();
You would need to perform the formatting at the time of the binding. As you don't show the actual binding code, it is hard to specifically address your situation but lets look at what happens in your query:
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo && z.ActivityDate >= EndDateTo && z.Indepth == false
select new { Date = z.ActivityDate.Date, Subject = z.Subject }).ToList();
Once LINQ handles this query, the resulting Query variable should be of type List<DateTime>. The way you have the query working you would return a list of DateTimes in a format like this:
2014-04-23 00:00:00
2014-03-28 00:00:00
etc...
In order to bind this without the time value, you need to call ToString() on each element (or the desired element) of the list at the time of binding.
Assuming you are using a ListBox or something similar you could write the following:
foreach (var date in myList) //this is the resultant list from the query
{
listBox1.Items.Add(date.ToString("MM/dd/yyyy");
}
If you are literally binding to a DataSource property, you will need to convert your List<DateTime> to a List<string> with the formatted values.
ToShortDateString() may help you.
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo
&& z.ActivityDate >= EndDateTo
&& z.Indepth == false
select new
{
Date = z.ActivityDate.ToShortDateString(),
Subject = z.Subject
}).ToList();
convert date into string like below
string stringDate=string.empty;
stringDate=Convert.ToDateTime("2014-04-23 00:00:00").ToShortDateString();
it will give output like
2014-04-23
How can I write this SQL statement using C# and LINQ? I am quering an Oracle database and the table has multiple revisions of the records. Therefore, I want onyl the current revision of each record contained in the table.
The SQL looks like this:
select TP_ID, TP_TEXT, TP_DEFN_SAKEY
from TP_DEFN tp1
where tp1.TP_ACTIVE_FLAG = 'Y' and
tp1.FAMILY_ID = 1 and
tp1.TP_DEFN_REV_DTS = (select max(TP_DEFN_REV_DTS)
from TP_DEFN tp2
where tp2.family_id = tp1.family_id and tp2.tp_id = tp1.tp_id )
order by TP_ID
TP_DEFN_REV_DTS is the date time field that stores the current revision.
I am a beginner with LINQ and have been struggling to find an workable solution. Every time that I try grouping in the LINQ query I get an error
GroupBy is not supported
Try something like this:
var res =
from tp1 in TP_DEFN
where tp1.TP_ACTIVE_FLAG == "Y" &&
tp1.FAMILY_ID == 1 &&
tp1.TP_DEFN_REV_DTS == (from tp2 in TP_DEFN
where tp2.FAMILY_ID == tp1.FAMILY_ID &&
tp2.TP_ID == tp1.TP_ID
select tp2.TP_DEFN_REV_DTS).Max()
orderby tp1.TP_ID
select new
{
tp1.TP_ID,
tp1.TP_TEXT,
tp1.TP_DEFN_SAKEY
};
Off the top of my head, and not knowing which LINQ provider you're using...
var q = from tp1 in Context.TP_DEFN
where tp1.TP_ACTIVE_FLAG == "Y"
&& tp1.FAMILY_ID == 1
&& tp1.TP_DEFN_REV_DTS
== Context.TP_DEFN.Where(tp2 => tp2.FAMILY_ID == tp1.FAMILY_ID
&& tp2.TP_ID == tp1.TP_ID)
.Max(tp2 => tp2.TP_DEFN_REV_DTS)
orderby tp1.TP_ID
select new
{
tp1.TP_ID,
tp1.TP_TEXT,
tp1.TP_DEFN_SAKEY
};
If you're using entity framework or linq-to-sql, you can just pass the direct sql if you want (although that'll prevent change tracking, at least by default).
For EF, use ObjectContext.ExecuteStoreQuery: http://msdn.microsoft.com/en-us/library/dd487208.aspx
For L2S, use DataContext.ExecuteQuery: http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.executequery.aspx