-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query: Provide EF.Functions to define methods that correspond to standard SQL operations #2850
Comments
@roji This does make sense in general although it is probably worth digging more into what "standard SQL operations" means 😄 We have talked within the EF team about the need to have a way to represent any standard relational functions as well as provider specific functions that aren't well represented by LINQ operators or by standard method calls in .NET BCL classes. We came up with a pattern we decided to try in EF7 that we believe can be better than what we had in the past. We just haven't found an opportunity to start using it, but would look similar to this: var legalMinors = context.People.Where(p =>
EF.Functions.DiffYear(p.BirthDate, DateTime.Now) -
DateTime.Now.DayOfYear < p.BirthDate.DayOfYear ? 1 : 0
< legalAge); The idea is to add a new Here are a few (subject to change) rules for these:
@ErikEJ It is true that |
Clearing up this for triage. I think we can choose having this issue in the backlog and up-for-grabs, or we can wait until the concrete need arises to have specific functions added. |
Sorry for disappearing for a while. @ErikEJ, Contains provides only a subset of what can be done with SQL LIKE (consider 'a%b%c') |
@divega, the approach looks great. Regarding rule 2, it might be acceptable for some methods to throw NotSupportedException rather than trigger client evaluation which if they aren't supported by a specific provider. This may encourage more unportable code, but would be more fail-fast (i.e. an exception is better than hard-to-detect slowdown due to client evaluation). Regarding rule 3, it seems cleaner for provider-specific functions to be defined in a provider-specific static class rather than have provider-specific prefixes on the EF.Functions class (i.e. Npgsql.EF.Functions.HostName() rather than EF.Functions.NpgsqlHostName()). |
@roji Re rule 2 (client evaluation vs. throwing not supported for performance reasons), client evaluation is actually one of the value adds of EF7 and I don't think we can always assume that evaluating something on the client is going to be so expensive than it is better not to do it. It will most likely depend heavily on how many rows will be returned that wouldn't if the function had been evaluated on the server, but in many cases it should be ok. For lack of a better strategy I think it is desirable to leave the decision to the application developer, e.g. think about having a simple Besides that, there is a class of functions that only have a real meaning on the server, e.g. the Re rule 3 (having |
+1 for the EF.Functions! Great discoverability, and no need to learn a new namespace |
Please consider making these methods (or at least most of them) work even at runtime if executed in a where statement for a mock database or in-memory one. The old approach with throwing as in DbFunctions has forced us to write our own wrapper where we have to duplicate all methods we use such as TruncateTime. +1 for trying to use BCL class calls instead of methods where possible so we for example might be able to write |
Any news with this feature? We are also forced to write our own wrapper where we have to duplicate all methods we use such as TruncateTime. |
It's not something our team will be tackling before the 7.0.0 release (purely due to time constraints). We haven't done any planning of what order we will tackle features after that release yet. We will do that planning (and share it publically) closer to the 7.0.0 release. |
Any news on this? |
@rjperes Nothing as yet. We have some higher priority features on the backlog, so this probably wont be in the first round of things we implement. |
Thanks, Rowan! See you in November, hopefully with EF Core 1.1 out! ;-) |
I am also very interested in having this implemented. |
I'd love to see TruncateTime implemented. |
To allow relational and providers to start defining extension methods on it. Modify SqlTranslatingExpressionVisitor to recognize the EFFunctions class and translate methods on it. Relates to dotnet#2850
Both with and without an escape character. Relates to dotnet#2850
To allow relational and providers to start defining extension methods on it. Modify SqlTranslatingExpressionVisitor to recognize the EFFunctions class and translate methods on it. Relates to dotnet#2850
Both with and without an escape character. Relates to dotnet#2850
@anpete @ajcvickers Thinking we may mark this as fixed in preview1. I believe we only have |
@divega Sounds good to me. |
Closing this as we have added the |
Can we have https://docs.microsoft.com/en-us/sql/t-sql/queries/freetext-transact-sql https://docs.microsoft.com/en-us/sql/t-sql/queries/contains-transact-sql |
I am trying to add an 'int Random(int, int)' function to EF.Functions but it looks like it is trying to evaluate it on the client rather than calling Random(int, int) on the DBS. I have added other database specific functions to EF.Functions and they work fine. Is there a way to tell EF to ALWAYS pass an extension function to the database? Someone above mentioned HostName as a potential extension function for PostgreSql. That would have the same issue so was that done/solved? (I understand there is a Random() function available in CLR but I need a random number generated for each row in the result set, so it must be executed on the database.) |
@MikeDempseyFL You can force EF to always send a function to the database by overriding the In your filter class inherit from |
@MikeDempseyFL Are you implementing a provider or are you just using EF Core in a project? |
I am implementing a provider.
rwasef1830 pointed me to the solution using IEvaluatableExpressionFilter service.
This works well.
Thanks
Mike
|
Hi @pmiddleton , I am a Ph.D. student. I am doing research about helping newcomers participate in OSS projects. I noticed that many projects are using labels such as 'good first issue/bug, help wanted' for issues to recommend that newcomers start from these tasks. I noticed that you tried to solve this issue, but unfortunately, you had not contributed successfully. I also found there are many newcomers feel difficult when submitting their first pr. Therefore, I want to optimize this mechanism, which needs your help. I have some questions and wish your valuable feedback. 1. What problems did you meet when solving this issue? I am looking forward to hearing from you soon. Thank you very much! |
It is possible to make use of the SQL functions by wrapping it with the DbFunctionAttribute. DbContext: public int? DatePart(string datePartArg, DateTime? date) => throw new Exception();
public void OnModelCreating(DbModelBuilder modelBuilder) {
var methodInfo = typeof(DbContext).GetRuntimeMethod(nameof(DatePart), new[] { typeof(string), typeof(DateTime) });
modelBuilder
.HasDbFunction(methodInfo)
.HasTranslation(args => new SqlFunctionExpression(nameof(DatePart), typeof(int?), new[]
{
new SqlFragmentExpression(args.ToArray()[0].ToString()),
args.ToArray()[1]
}));
} Query: repository.GroupBy(x => dbContext.DatePart("week", x.CreatedAt)); some more info: #10404 |
for EF core 3 is little different solution:
|
Tried this implementation on EF Core 3.1.3 but it doesn't work:
Registered the function like this on the DB context:
|
@rangelier can you please open a new issue and include a minimal, runnable code sample? The actual LINQ query is missing from the above. |
yes, need to some time to prepare though. The original query looks like this:
|
anything new on this issue? |
this works fine for us, even on v3.1.9 |
@divega The repeatedly requested TruncateTime methods have not been implemented in DbFunctions, despite it being mentioned repeatedly above: #2850 (comment), #2850 (comment), #2850 (comment), #2850 (comment) How can you compare a date to the start/end of the day? This issue which explicitly requested the TruncateTime functions got marked as closed/dupe, even though the implementation did NOT resolve it. Can you please re-open so we don't have to re-file another one for the exact same thing? |
Not sure whether this has already been discussed (or makes sense).
There are some standard SQL operations that don't correspond to an already-existing .NET method; the example that comes to mind is LIKE. It seems that up to now, each provider invented its own way to allow users to specify these in LINQ to Entities - SqlClient has SqlFunctions and SqlMethods.
It seems to makes sense to pull the standard SQL functions and methods out of these SQL Server-specific classes and place them in the generic EF7 code, this way the same LINQ can be used across different providers...
The text was updated successfully, but these errors were encountered: