How to query datetime literals and null values in Linq predicate? - c#

In my current query I'm having an error like this:
The datetime literal value '2012-05-24' is not valid.
For regular linq query it seems like this:
_listHistory = (from item in dbase.histories
where item.UserID == details.UserID && item.FriendID.HasValue == true && item.LogDate < today
select item).OrderByDescending(x => x.LogDate).Take(take).Skip(skip).ToList();
I will be dealing with number of table "Columns" so I have to use linq predicate:
string predicate = string.Format("it.UserID=={0} && CAST(it.{1} as Edm.Int64) != null && it.LogDate <= DATETIME'{2}'",
details.UserID, columnname, string.Format("{0:yyyy-MM-dd}", today));
_listHistory = dbase.histories.Where(predicate)
.OrderByDescending(x => x.LogDate).Take(take).Skip(skip).ToList();
But this query result the error above. Can anyone help me to construct my linq query?
It is my first time to deal with Linq predicates and literals.

You could likely use the dynamic LINQ support instead, but assuming this is Entity Query Language, it appears that you can construct the datetime with a call to CreateDateTime:
http://msdn.microsoft.com/en-us/library/bb738563.aspx
CreateDateTime( year, month, day, hour, minute, second)

Related

LINQ Query to Convert numeric to datetime in where clause

I have a field with datatype numeric and I have stored hour values in it. Now I want to subtract the hours of a DateTime field with the numeric field and compare it with DateTime.Now() in a where clause of LINQ query. i'm using this logic `private List GetInterviewExamSlots(int programPreferenceId, string lookuptype)
{
var currentDateTime = DateTime.UtcNow;
var schedules = uow.RepositoryAsync<CoC_Schedule_Entry>()
.Queryable()
.AsNoTracking()
.OrderByDescending(x=> x.Start_Datetime)
.Where(x => x.Capacity != null &&
x.Capacity != 0 &&
(x.Start_Datetime).AddHours((double)- x.Event_Registration_Deadline) > currentDateTime &&
x.Fully_Booked_Flag != Constants.YesFlag &&
x.CoC_Schedule_Entry_Type.Schedule_Entry_Type_Code.Equals(lookuptype) &&
x.CoC_Lookup3.Hidden_Value.Equals(LookupCodes.OpenHiddenValue)
&& (x.Program_Preference_ID == programPreferenceId
||
x.Program_Preference_ID == null))
.Select(x => new ............`
but it throws an exception LINQ to Entities does not recognize the method '.AddHours' method and this method cannot be translated into a store expression.
Not everything, that can be expressed in C# can be translated to the store's language. What this is, depends on the specific store and the LINQ provider (like e. g. entity framework for sqlserver). In your case the provider can't translate the AddHours function call.
To get past this you can
remove the method call from your query, convert the result to something that can be queried via Linq2Objects (e. g. by adding .ToList() to convert your (intermediate) result to a List<...>) and then query it again. Now that nothing needs to be translated, AddHours (and any other function call) will work.
Depending on your data this might consume many local resources.
var preSelectedSchedules = uow.RepositoryAsync<CoC_Schedule_Entry>()
.Queryable()
.AsNoTracking()
.OrderByDescending(x=> x.Start_Datetime)
.Where(x => x.Capacity != 0
&& x.Fully_Booked_Flag != Constants.YesFlag
&& x.CoC_Schedule_Entry_Type.Schedule_Entry_Type_Code.Equals(lookuptype)
&& x.CoC_Lookup3.Hidden_Value.Equals(LookupCodes.OpenHiddenValue)
&& (x.Program_Preference_ID == programPreferenceId
|| x.Program_Preference_ID == null))
.ToList();
var schedules = preSelectedSchedules
.Where(x => x.Start_Datetime.AddHours(-x.Event_Registration_Deadline) > currentDateTime)
.Select(...);
provide a query in the store's language (like a view if we're talking about sql) which returns the desired data and you use this a the data source of your query.
If you have very few different values for x.Event_Registration_Deadline, you can also try another approach:
select all distinct values for x.Event_Registration_Deadline
for each value calculate var theshold = currentDateTime.AddHours(<value>);
perform the query with .Where(x => x.Start_Datetime > threshold)

LINQ to Entities does not recognize the method?

var tmp = productDBSet.Where(x => x.lastUpdate >= DateTime.MinValue && x.lastUpdate.Value.ToString("MM/yyyy") == curMonth).Select(x => x.ID);
While I run above code, I got this error message:
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated
into a store expression.
Also I tried,
var tmp = productDBSet.Where(x => x.lastUpdate >= DateTime.MinValue && x.lastUpdate.Value.ToString("MM/yyyy") == curMonth).ToList().Select(x => x.ID);
But same,
How can I solve that?
As the error message is telling you, the ToString method of DateTime isn't supported.
Since you're just trying to determine if the month and year of the date match a given value, you can just compare the actual month and year, rather than trying to get a string containing the month and year that you compare with.
x.lastUpdate.Value.Year == yearToCompareWith &&
x.lastUpdate.Value.Month = monthToCompareWith
You cannot use ToString() in Linq to Entities. Try something like this (I've assumed that x.lastUpdate is of type "DateTime"):
x.lastUpdate.Month == curMonth && x.lastUpdate.Year == curYear
This happens, because LINQ to Entities is translated to SQL queries, and therefore method ToString is not recognised.
You can not use extension methods in linq queries, since these are unable to get converted to equivalent Sql Queries. You can use following linq:
var tmp = productDBSet.Where(x => x.lastUpdate >= DateTime.MinValue && x.lastUpdate.Month == curMonth && x.lastUpdate.Year == curYear).Select(x => x.ID);

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?

Convert string to long type and use in a linq query within asp.net MVC

Is it possible within Linq in C#, to convert a string field in a database, to a long type - and use it in the query?
Here, tme is a unix time (long) - but the field in the database, targetdate - is a string.
I've tried:
var qbt = db.Calls
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
However I get the message: LINQ to Entities does not recognize the method 'Int64 Parse(System.String)' method, and this method cannot be translated into a store expression.
I know you can convert before the linq query, but is there any way of using it WITHIN the linq query?
Thanks for any help,
Mark
try
var qbt = db.Calls.ToList()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
if you have many records you can limit them by team first and then call ToList like below
var qbt = db.Calls.Where(x => x.team == id).ToList()
.Where(i=>long.Parse(i.targetdate) <= tme);
Or You can use AsEnumerable
var qbt = db.Calls.AsEnumerable()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
This is to do with the way the Linq is translated into the backing query language, it might be easier to do a string comparison in this case, using tme.ToString(). If you pull the full collection down first, you could query like this but that means what it says: pulling down the full unfiltered (or at least less filtered) set.
You have to either change the database table to not store a string (you could create a computed column that converts it to a long or create a view if you cannot modify the existing table) or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.
var stringTme = tme.ToString(CultureInfo.InvariantCulture);
var qbt = db.Calls
.Where(x => x.team == id && ((x.targetdate.Length < stringTme.Length)
|| (x.targetdate.Length == stringTme.Length && x.targetdate <= stringTme)));
You have to either change the database table to not store a string or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.please use long.Parse()

How can i use DateTime.AddXXXX functions in a Linq-to-Entities query?

I am trying to use AddMonths in a query
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true && s.SubscriptionDateTime < DateTime.Now.AddMonths(-1)
select s).ToList();
But I recieve an error :
LINQ to Entities does not recognize the method 'System.DateTime
AddMonths(Int32)' method, and this method cannot be translated into a
store expression.
Is there a way I can use this function inside my query?
The simplest fix to this is to work out the time limit once before using LINQ:
DateTime limit = DateTime.Now.AddMonths(-1);
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true &&
s.SubscriptionDateTime < limit)
select s).ToList();
Or more readably IMO:
var items = context.Subscribers
.Where(s => !s.Validated &&
s.ValidationEmailSent &&
s.SubscriptionDateTime < limit)
.ToList();
There's no benefit in using a query expression here, and explicit comparisons with true and false are ugly IMO (unless your properties are of type Nullable<bool> of course).
Jon Skeet has already provided a simple fix, but if you want the DateTime.Now.AddMonths bit to run on the database, try the EntityFunctions.AddMonths method.
This is a more general approach that is especially useful when you cannot replicate the expression cheaply or correctly on the client.
You can change your code to:
DateTime oneMonth = DateTime.Now.AddMonths(-1)
List<Entities.Subscriber> items = (from s in context.Subscribers
where s.Validated == false && s.ValidationEmailSent == true && s.SubscriptionDateTime < oneMonth
select s).ToList();
You have to do this because AddMonth is a .NET function that can't be translated into SQL by Linq to Entities. Perform the calculation in your code and then use the resulting datetime will work.

Categories

Resources