SqlMethods.DateDiffMonth in the Entity Framework - c#

Does anyone know what is the replacement for SqlMethods.DateDiffMonth in the Entity Framework.
This is the error I am getting when I tried to use it.
LINQ to Entities does not recognize the method 'Int32 DateDiffMonth(System.DateTime, System.DateTime)' method, and this method cannot be translated into a store expression.

It would appear that, currently, you need to express this using an eSQL statement that effectively calls down to the SQLServer DATEDIFF method
For example:
db.entity.Where("SqlServer.DATEDIFF('MONTH', [start date], [end date]) = 1");
(See here for further info)
However, when the .NET Framework Version 4.0 is released (or you can use it now if you like playing with beta software! :) you should be able to use the DateDiff method of the new SqlFunctions class, which is part of the new System.Data.Objects.SqlClient Namespace in .NET 4.0

Since you are using LINQ to Entities the best way would be to use the following:
var query = query.Where(e => DateTime.Today >= EntityFunctions.TruncateTime(e.StartDateTime)
&& DateTime.Today <= EntityFunctions.TruncateTime(e.EndDateTime));

Related

Entity Framework equivalent of SQL relative update

If I want to increase the value in a table column with SQL I can do it as follows:
UPDATE mytable m SET m.mycolumn = m.mycolumn + 1;
This is great because it doesn't rely on being executed in any order and uses an absolute minimum of locking.
How can this be done using C# and Entity Framework, with the same (or as close as possible) minimal overhead?
In short, you can't. You can execute a sql statement through the ado.net properties available on the DbContext.Database. You could also created a stored procedure if this is a specific action that occurs where the stored proc does this. That is the closest you will get to this.
This answer assumes you already know how to retrieve all the records, iterate over them to change the value of the property, and then persist the changes using SaveChanges on the DbContext and that this is not what you are looking for as it generates 1 update statement per record.
As already said, it's not possible in Pure EF.
As always you're free to create your pure SQL statements and run them through your context.
The closest thing to your question is to use Entity Framework Extensions. The have an UpdateFromQuery method: https://entityframework-extensions.net/update-from-query
This would look like this:
context.mytable.UpdateFromQuery(x => new mytable() {mycolumn = x.mycolumn + 1});
You can use EF Core extension linq2db.EntityFrameworkCore (disclaimer: I'm one of the creators)
context.mytable
.Set(x => x.mycolumn, x => x.mycolumn + 1)
.Update();
Library has it's own LINQ Translator which eliminates a lot of EF Core limitations.
dbContext.Entity.ForEach(x -> x.property = value);
or
dbContext.Entity.Select(x -> {x.property =100; return c;}).ToList();
See Using LINQ to Update A Property in a List of Entities

TimeSpan Issue in EF Core 3.1

I have a problem querying PostgreSQL database using EF Core 3.1.
The query is very simple
var gamesQuery = this.dbContext.Games.Where(game => game.StartTime > DateTime.Now).AsQueryable();
// 'request.TimeFrom' is of type System.TimeSpan and the value is populated
gamesQuery = gamesQuery.Where(game => game.StartTime.TimeOfDay >= request.TimeFrom);
// .ToList()-int here causes the exception.
var games = gamesQuery.ToList();
The exception message clearly states that the query can not be translated:
"The LINQ expression 'DbSet\r\n .Where(g => g.StartTime > DateTime.Now)\r\n .Where(g => g.StartTime.TimeOfDay >= __request_TimeFrom_0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information."
The problem is that the same query works fine in .NET Core 2.2.
I haven't found anything about the problem yet.
Someone know what is the reason about this one or am I missing something?
Currently PostgreSQL EF Core 3.x query provider does not support translation of DateTime.TimeOfDay - see the TODO comment in the source code.
Most likely it "worked" in 2.x by silently using client evaluation. But implicit client evaluation has been removed in 3.0 and there is no way to turn it back on.
You can try the following equivalent construct:
.Where(game => (game.StartTime - game.StartTime.Date) >= request.TimeFrom)
At least it doesn't produce the aforementioned exception.
If it doesn't work, take their advice and switch explicitly to client evaluation by inserting AsEnumerable() in the appropriate place before the non translatable expression.
I haven't tried this yet but one solution could be to save TimeOfDay into database beside of DateTime property. Then you just compare it with your TimeSpan variable.

How to Compare Only Date of dateTime objects in EF [duplicate]

_dbEntities.EmployeeAttendances.Where(x => x.DailyDate.Date.Equals(DateTime.Now.Date)).ToList();
"The specified type member 'Date' is not supported in LINQ to
Entities. Only initializers, entity members, and entity navigation
properties are supported."
How can i do this get employees data on based on current date in linq query?
EntityFramework cannot convert DateTime.Date to SQL. So, it fails to generate expected SQL. Instead of that you can use EntityFunctions.TruncateTime() or DbFunctions.TruncateTime()(based on EF version) method if you want to get Date part only:
_dbEntities.EmployeeAttendances
.Where(x => EntityFunctions.TruncateTime(x.DailyDate) == DateTime.Now.Date)
.ToList();
Additional info:
EntityFunctions methods are called canonical functions. And these are a set of functions, which are supported by all Entity Framework providers. These canonical functions will be translated to the corresponding data source functionality for the provider. Canonical functions are the preferred way to access functionality outside the core language, because they keep the queries portable.
You can find all canonical functions here and all Date and Time Canonical Functions here.
Update:
As of EF6 EntityFunctions has been deprecated for System.Data.Entity.DbFunctions.
Dont use EntityFunctions in EF 6. TruncateTime is in the DbFunctions class:
DbFunctions.TruncateTime(x.DailyDate)
If the DailyDate property is already just a date, instead of a date and time, then it would be simplest to just use:
// Outside the query so it becomes a constant, effectively
var today = DateTime.Today;
var employees = _dbEntities.EmployeeAttendances
.Where(x => x.DailyDate == today)
.ToList();
If it does have times (making the above fail), you could always use:
// Outside the query so it becomes a constant, effectively
var today = DateTime.Today;
var tomorrow = today.AddDays(1);
var employees = _dbEntities.EmployeeAttendances
.Where(x => x.DailyDate >= today &&
x.DailyDate < tomorrow)
.ToList();
... or use TruncateTime as Farhad's answer suggests. I'd still recommend evaluating DateTime.Today first though:
var today = DateTime.Today;
var employees = _dbEntities.EmployeeAttendances
.Where(x => EntityFunctions.TruncateTime(x.DailyDate) == today)
.ToList();
Note that Today (like DateTime.Now) uses the system default time zone. You should think carefully about whether that's what you want.
Just in case it helps someone...
In EF 6, EntityFunctions is obsolete, use DbFunctions class instead.
You might want to include the Namespace System.Data.Entity;
eg:
_dbEntities.EmployeeAttendances.Where(x => DbFunctions.TruncateTime(x.DailyDate) == DateTime.Now.Date).ToList();

LINQ to entities : cannot call a method

I'm aware there are alreay a lot of posts concerning this issue, but i can't seem to find a solution for this.
Here's my Ling to Entities query :
IEnumerable<Tblstamp> changes = (from c in userGSN.edb.Tblstamp
where (c.Ts_Date >= userGSN.DateLastCheck &&
TimeSpan.Parse(c.Ts_Time) >= userGSN.TimeLastCheck)
orderby c.Ts_Id ascending
select c);
I want to compare c.Ts_time to userGSN.TimeLastCheck, but for that I have to convert the c.Ts_Time to a timespan (it is a string, and comes from a database I can't modify, tried everything). I also can't do the converting before the query in an other variable since I can't access it outside of the query.
Obviously, I get an error for trying to use the TimeSpan.Parse method in my query, but I can't find any workaround to this. I have tried using LINQ to Object but since I am really not used to it I couldn't make the equivalent query that i have here.
I am aware of the problem, I'm just trying to find a workaround and need some help please !
EDIT :
So I tried the DateDiff function as suggested :
IEnumerable<Tblstamp> changes = (from c in userGSN.edb.Tblstamp
where (c.Ts_Date >= userGSN.DateLastCheck && SqlFunctions.DateDiff("second",userGSN.TimeLastCheck,c.Ts_Time).Value > 0 )
orderby c.Ts_Id ascending
select c
);
but it gives me the same error : "LINQ to Entities does not recognize the method 'System.Nullable1[System.Int32] DateDiff(System.String, System.Nullable1[System.TimeSpan], System.String)' method, and this method cannot be translated into a store expression."
Even though it clearly says here "You cannot call this function directly. This function can only appear within a LINQ to Entities query.", which is exactly what I'm doing ?!
There's no clean way to do this, so you'll have to think outside the box. Try using SqlFunctions.DateDiff to perform the check. You'll need to adapt it for your usage, but:
SqlFunctions.DateDiff("second", c.Ts_Time, userGSN.TimeLastCheck.ToString()) > 0
There are other methods that you can use, if DateDiff is not suitable. See EntityFunctions as well.
Depending on what you're using to query the data, you might want System.Data.Entity.SqlServer.SqlFunctions instead.
Every code you write in LinQ to get data from database must convert to a valid T-SQL query with valid statements. Not all C# methods have a correspondance in T-SQL so whenever you use them in your code while fatching data you will get errors.
You should either do modifications on the SQL side or use C# spesific functions after fething data from database, while working with entities in memory, or use fıunstions which comply with SQL statements.
If you can't get EF to translate your query to SQL, maybe you could do it yourself? See Writing SQL queries for entities
Linq to Entities does not support all functions since the query has to be translated to SQL:
from c in userGSN.edb.Tblstamp.AsEnumerable()
//now you are allready getting the data from the database
//so be carefull with that because you will have bad performance

How to specify index in Entity Framework 5.0

I have a select statement where it returns thousands of records. i want to use Index hints with the query. How do i do this using Entity Framework
var actCosts = db.ActCosts.Where(t => t.ScenarioID == scenarioID).ToList();
like this
select * from ActCost WITH(INDEX(IX_ActCost_ScenarioID)) where ScenarioID = 797
There is no way of adding query hints to the current version of Entity Framework; however, they are considering implementing it in a future release.
See the proposal at https://entityframework.codeplex.com/workitem/261 as well as some possible work-arounds.

Categories