Exception when comparing dates - Npgsql.PostgresException: '42883' - c#

I'm trying to get records with a date that are the same or later than a given date. But this Exception keeps happening:
Npgsql.PostgresException: '42883: operator does not exist: character varying >= timestamp without time zone'
And here is my code:
var bairro = "test";
var dataBusca = DateTime.Now.AddDays(-7).ToString("yyyy-MM-dd");
var buscaImovel = _context.ImovelModel
.Where(context => context.bairronome == bairro &&
context.datageracaoarq >= DateTime.Parse(dataBusca)).ToList(); //exception happens here
The dates in my database are using the "yyyy-MM-dd" timestamp. What could be the problem?

LINQ could not translate the expression if I casted the field to DateTime in it. The solution was changing the field type in the database to 'date'.

Related

Function date_trunc does not exist

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();

Linq - between dates query

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?

Compare a Part of the date using linq

I need to compare, using LINQ, a date string "2010-06-11" with a field value in the database "2013-07-25 14:33:58.070", but only the year-month-day part.
I tried this:
updateDate = "2010-06-11";
_adRepository.Query.Where(p => p.DateModified.ToString("YYYYMMDD") <= updateDate).FirstOrDefault();
but it's not working, any ideas?
Thanks.
One of the problems not mentioned earlier is that the test data you're using will always fail to return a value. "2013-07-25" will never be less than "2010-06-11".
That being said, your code really should be converting the updateDate variable into a date time and doing the comparison against that rather than converting the DateModifed field in the table. Otherwise the conversion is applied against all of the records in the database. The code I would use is:
var updateDateString = "2010-06-11";
DateTime updateDate;
if (DateTime.TryParse(updateDateString, out updateDate))
{
_adRepository.Query.Where(p => p.DateModified <= updateDate).FirstOrDefault();
}
else
{
// throw an exception or something
}
This should work:
_adRepository.Query.Where(p => p.DateModified.Day <= DateTime.Parse(updateDate).Day);
It might have some issues with parse, but I can't remember proper format for it.
Date format is incorrect. You want "yyyyMMdd". But this is trying to get linq to do a string compare. If you are using EF it probably won't work.
Convert UpdateDate to a DateTime instead and use that in your query.
from q in _adRepository.Query
where DateTime.Compare(updateDate.Date, DateTime.Parse(q.DateModified).Date) <= 0
select q
try this:
DateTime updateDate = DateTime.Today;
_adRepository.Query.Where(p => p.DateModified.Date <= updateDate).FirstOrDefault()
This works in LinqPad
DateTime[] update = new DateTime[]{ new DateTime(2014,01,01), new DateTime(2014,01,29), new DateTime(2014,01,22)};
var selected = update.Where(x => x.Date <= new DateTime(2014,01,22).Date);

Get the lowest year from LINQ query results

I am trying to find the earliest year from a group of rows returned by a LINQ query. The ActivationDate is stored as a datetime value in the DB.
I know that I can make a separate query to get just the date, but I would rather use the results from the existing query, as it is used for several other things.
IEnumerable<MonitoringPanel> panels = from rows in db.MonitoringPanels
where rows.DealerEntity == dealerIDint
select rows;
However this keeps throwing an error:
var testDate = panels.Min().ActivationDate;
Error:
System.ArgumentException was unhandled by user code.
It will throw an error even if I try to select the lowest PanelNumner (stored as an int), but the following does work:
var testDate = panels.FirstOrDefault().ActivationDate;
Solution
DateTime testDate = (DateTime)panels.Min( thing => thing.ActivationDate);
int lowYear = testDate.Year;
Unless the Enumerable is of a perimative type you need to add a lambda expression to tell it what property of the class to use. Try
var testDate = panels.Min(x => x.ActivationDate);
I think you need to tell the Min() method what to look for the Minimum of. Which field is the Minimum.
var testDate = panels.Min(panel => panel.ActivationDate);

How to compare only date components from DateTime in EF?

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();

Categories

Resources