I have a C# query using linq with two datetime fields Im trying to compare. The datetime field in the Postgres DB is stored as timestamp with time zone. However for some reason I am receiving "function date_trunc(unknown, timestamp with time zone, unknown) does not exist" error although in the debug view it shows I am passing the correct parameters. Please note: MyDate field is Nullable
C#
_context.MyDbObject.Where(a => DateTime.UtcNow.Date >= a.MyDate.Value.Date).AsQueryable();
Query shown in Debug View
(date_trunc('day', now(), 'UTC') >= date_trunc('day', a."MyDate", 'UTC')))
Error
MessageText: function date_trunc(unknown, timestamp with time zone, unknown) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
It is not direct answer to your question, but if you care about database indexes, do not use date truncation in queries. Your query can be rewritten.
var currentDate = DateTime.UtcNow.Date;
var endDate = currentDate.AddDays(1);
var query = _context.MyDbObject
.Where(a => a.MyDate.Value < endDate)
.AsQueryable();
// or records for current day
var query = _context.MyDbObject
.Where(a => a.MyDate.Value >= currentDate && a.MyDate.Value < endDate)
.AsQueryable();
I have a database with a string column that indicates a datetime value with this format: yyyyMMdd.
For example the value 20160908 indicate the 08 of Semptember 2016.
I have two datetimepicker for filter dateFrom and dateTo value. I take the datetime value in my datepicker textbox with this simply code:
DateTime dataFromSel = Convert.ToDateTime(txtDatFrom.Text);
DateTime dataToSel = Convert.ToDateTime(txtDatTo.Text);
My query is:
var query = from c in snd.WineOWines.OrderByDescending(x => x.DDT_DATA)
select new
{
c.ID,
c.VABRMA,
c.VABNCL,
c.DDT_DATA,
};
If I have a datetime filter i add this code:
if (txtDatDa.Text != "")
{
string dataDaSel = Convert.ToDateTime(txtDatDa.Text).ToString("yyyyMMdd");
int dataDa = Convert.ToInt32(dataDaSel);
query = query.Where(x => int.Parse(x.DDT_DATA) >= dataDa);
}
The problem is that i can't to list the query before the filter because i have a lot of rows and if i use this query i can't do an int.parse in the LINQ statement.
How can i write a LINQ statement that select the row in my DB with datetime between from and to, if the value in the column is a string?For now my query works fine, but i need a where clause for this problem.
Thanks to all
If dates have the same format you do not need to cast them to int.
You should be able to compare stings and remove the cast...
if (!string.IsNullOrEmpty(txtDatDa.Text))
{
string dataDaSel = Convert.ToDateTime(txtDatDa.Text).ToString("yyyyMMdd");
var res = query.Where(x => string.Compare(dataDaSel, x.Name) <= 0);
}
Linq to SQL supports string.Compare(string, string) as described here
https://social.msdn.microsoft.com/Forums/en-US/98180ae0-4ccd-4ecd-89d5-576a04169219/linq-to-entities-with-string-comparison?forum=adodotnetentityframework
You don't have to put int.Parse, you can do a direct string comparison it is going to work ok. Neither you have to convert your dataDaSel into integer.
if (txtDatDa.Text != "")
{
string dataDaSel = Convert.ToDateTime(txtDatDa.Text).ToString("yyyyMMdd");
query = query.Where(x => x.DDT_DATA >= dataDaSel);
}
E.g.
"20120201" >= "20120201" // true
"20120101" >= "20120201" // false
"20120301" >= "20120201" // true
As long as you keep format as yyyyMMdd it is going to work ok even with string.
I have a date variable named start that is passed in a query-string. Using linq I need to test on another page if another date variable named StartDate equals the date variable passed in the url.
I'm attempting to do something like:
test = client.GetEventInstances().Where(e => e.StartDate == start);
I can then filter by events with a StartDate that is equal to my start var sent in the url
You need to convert your string date to DateTime:-
DateTime startDate = DateTime.Parse(start);
test = client.GetEventInstances().Where(e => e.StartDate.Date == startDate.Date);
Obviously you will have to check whether date was parsed or not.
You should use DateTime.TryParse()
DateTime startDateTime;
if (DateTime.TryParse(start, out startDateTime))
client.GetEventInstances().Where(e => e.StartDate.Date == startDateTime.Date);
else
/* query can't be parsed, do whatever you need to do */
I am trying to convert the following sql query as a linq query, however I keep experiencing an error -
Operator '<=' cannot be applied to operands of type 'string' and 'System.DateTime'.
SQL Query:
select top 3 Deal, [property], [event], [Date] from [dbo]. [Database_CRE_Events]
where (convert(datetime,[Date],103) between '01-May-2015' and '15-May-2015') and [property] is not NULL
order by convert(datetime,[Date],103) desc
I believe this is happening because c.Date is a string field from the entity database. I have tried converting the date values to string and datetime to get the following to work, but I keep getting an operand error.
LINQ Query:
DateTime dat = DateTime.Now.AddDays(-10);
string preWeek = dat.ToString("dd-MMM-yyyy");
DateTime dtt = DateTime.Now;
string today = dat.ToString("dd-MMM-yyyy");
var data = db.Database_CRE_Events.Where(c => c.Date <= Convert.ToDateTime(preWeek) && c.property != null)
.Select(x => new Loan() { Name = x.Deal, loan = x.property, evnt = x.Event })
.ToList().Take(3);
return data;
Is it possible to convert the original sql query to a linq query as c.Date being a string parameter?
Thank you for any further assistance.
The problem is that you're introducing strings into the mix for no reason at all. Unless you have to convert a DateTime to or from a string, don't do it.
Your query should be as simple as:
DateTime preWeek = DateTime.Today.AddDays(-10);
var data = db.Database_CRE_Events
.Where(c => c.Date <= preWeek && c.property != null)
.Select(x => new Loan() { Name = x.Deal, loan = x.property, evnt = x.Event })
.ToList()
.Take(3);
return data;
If c.Date is actually a string, you should fix your database so that it isn't a string. It's meant to be a date, so represent it as a date! If you absolutely have to keep it as a string, you should at least use a sortable format, such as yyyy-MM-dd. At that point you could use CompareTo - but it's horrible :(
If the format is dd-MMM-yyyy (as it sounds) you could try performing the parse in the LINQ query, still passing in a DateTime but parsing each value in the database:
.Where(c =>
DateTime.ParseExact(c.Date, "dd-MMM-yyyy", CultureInfo.InvariantCulture) <= preWeek
&& c.property != null)
... but I wouldn't be surprised if that fails. You may want to add a view in SQL which gives a more appropriate version of the data. Fundamentally, if you have to work with a broken schema (in this case using the wrong type and making a poor decision about how to format the data within that type) then you should expect pain. Pass this pain up to managers in order to prioritize changing the schema...
Notes:
You're fetching all the data, and then just taking the first three elements. That's a bad idea. Switch round the calls to ToList and Take after addressing the next bullet...
"First three elements" is only meaningful with ordering. Use OrderBy to specify an ordering
You're not currently using today, so I removed it
If you're only interested in a date, use DateTime.Today
You should carefully consider time zones, both in your database and in your calling code. This is currently using the system default time zone - is that what you want?
I am having two date values, one already stored in the database and the other selected by the user using DatePicker. The use case is to search for a particular date from the database.
The value previously entered in the database always has time component of 12:00:00, where as the date entered from picker has different time component.
I am interested in only the date components and would like to ignore the time component.
What are the ways to do this comparison in C#?
Also, how to do this in LINQ?
UPDATE:
On LINQ to Entities, the following works fine.
e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0
Use the class EntityFunctions for trimming the time portion.
using System.Data.Objects;
var bla = (from log in context.Contacts
where EntityFunctions.TruncateTime(log.ModifiedDate) == EntityFunctions.TruncateTime(today.Date)
select log).FirstOrDefault();
Source: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/
UPDATE
As of EF 6.0 and later EntityFunctions is replaced by DbFunctions.
NOTE: at the time of writing this answer, the EF-relation was unclear (that was edited into the question after this was written). For correct approach with EF, check Mandeeps answer.
You can use the DateTime.Date property to perform a date-only comparison.
DateTime a = GetFirstDate();
DateTime b = GetSecondDate();
if (a.Date.Equals(b.Date))
{
// the dates are equal
}
I think this could help you.
I made an extension since I have to compare dates in repositories filled with EF data and so .Date was not an option since it is not implemented in LinqToEntities translation.
Here is the code:
/// <summary>
/// Check if two dates are same
/// </summary>
/// <typeparam name="TElement">Type</typeparam>
/// <param name="valueSelector">date field</param>
/// <param name="value">date compared</param>
/// <returns>bool</returns>
public Expression<Func<TElement, bool>> IsSameDate<TElement>(Expression<Func<TElement, DateTime>> valueSelector, DateTime value)
{
ParameterExpression p = valueSelector.Parameters.Single();
var antes = Expression.GreaterThanOrEqual(valueSelector.Body, Expression.Constant(value.Date, typeof(DateTime)));
var despues = Expression.LessThan(valueSelector.Body, Expression.Constant(value.AddDays(1).Date, typeof(DateTime)));
Expression body = Expression.And(antes, despues);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
then you can use it in this way.
var today = DateTime.Now;
var todayPosts = from t in turnos.Where(IsSameDate<Turno>(t => t.MyDate, today))
select t);
If you use the Date property for DB Entities you will get exception:
"The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
You can use something like this:
DateTime date = DateTime.Now.Date;
var result = from client in context.clients
where client.BirthDate >= date
&& client.BirthDate < date.AddDays(1)
select client;
To do it in LINQ to Entities, you have to use supported methods:
var year = someDate.Year;
var month = ...
var q = from r in Context.Records
where Microsoft.VisualBasic.DateAndTime.Year(r.SomeDate) == year
&& // month and day
Ugly, but it works, and it's done on the DB server.
Here's a different way to do it, but it's only useful if SecondDate is a variable you're passing in:
DateTime startDate = SecondDate.Date;
DateTime endDate = startDate.AddDays(1).AddTicks(-1);
...
e => e.FirstDate.Value >= startDate && e.FirstDate.Value <= endDate
I think that should work
You can also use this:
DbFunctions.DiffDays(date1, date2) == 0
you can use DbFunctions.TruncateTime() method for this.
e => DbFunctions.TruncateTime(e.FirstDate.Value) == DbFunctions.TruncateTime(SecondDate);
Just always compare the Date property of DateTime, instead of the full date time.
When you make your LINQ query, use date.Date in the query, ie:
var results = from c in collection
where c.Date == myDateTime.Date
select c;
This is how I do this.
DateTime date_time_to_compare = DateTime.Now;
//Compare only date parts
context.YourObject.FirstOrDefault(r =>
EntityFunctions.TruncateTime(r.date) == EntityFunctions.TruncateTime(date_to_compare));
//Note for Linq Users/Coders
This should give you the exact comparison for checking if a date falls within range when working with input from a user - date picker for example:
((DateTime)ri.RequestX.DateSatisfied).Date >= startdate.Date &&
((DateTime)ri.RequestX.DateSatisfied).Date <= enddate.Date
where startdate and enddate are values from a date picker.
Without time than try like this:
TimeSpan ts = new TimeSpan(23, 59, 59);
toDate = toDate.Add(ts);
List<AuditLog> resultLogs =
_dbContext.AuditLogs
.Where(al => al.Log_Date >= fromDate && al.Log_Date <= toDate)
.ToList();
return resultLogs;
You can user below link to compare 2 dates without time :
private bool DateGreaterOrEqual(DateTime dt1, DateTime dt2)
{
return DateTime.Compare(dt1.Date, dt2.Date) >= 0;
}
private bool DateLessOrEqual(DateTime dt1, DateTime dt2)
{
return DateTime.Compare(dt1.Date, dt2.Date) <= 0;
}
the Compare function return 3 different values: -1 0 1 which means dt1>dt2, dt1=dt2, dt1
Try this... It works fine to compare Date properties between two DateTimes type:
PS. It is a stopgap solution and a really bad practice, should never be used when you know that the database can bring thousands of records...
query = query.ToList()
.Where(x => x.FirstDate.Date == SecondDate.Date)
.AsQueryable();
I have resolved error using EfCore FromSqlRaw method.
var sql =
$"select * from \"ProgressBooks\" where date(\"Date\") = date('{today.Date.ToString("yyyy-MM-dd")}') and \"GroupId\" = {groupId}";
var todayProgressBook = _context.ProgressBooks.FromSqlRaw(sql).FirstOrDefault();