From 97aca4b76633142b4b122ae5840fea3cf4fe39e9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 23:16:18 +0000 Subject: [PATCH 1/3] Initial plan From 5b9e71384f1746cc86ce84069d0a6fcfba62ad8a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Aug 2026 23:22:06 +0000 Subject: [PATCH 2/3] Document aggregate and built-in functions Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../core/providers/sql-server/functions.md | 4 +- .../core/providers/sqlite/functions.md | 4 +- .../core/querying/complex-query-operators.md | 41 ++++++++++++++++++- .../querying/user-defined-function-mapping.md | 18 +++++++- .../UserDefinedFunctionMapping/Model.cs | 11 +++++ 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/entity-framework/core/providers/sql-server/functions.md b/entity-framework/core/providers/sql-server/functions.md index a39bc6d151..9c00130d5e 100644 --- a/entity-framework/core/providers/sql-server/functions.md +++ b/entity-framework/core/providers/sql-server/functions.md @@ -2,7 +2,7 @@ title: Function Mappings - Microsoft SQL Server Database Provider - EF Core description: Function Mappings of the Microsoft SQL Server database provider author: SamMonoRT -ms.date: 4/14/2026 +ms.date: 08/19/2026 uid: core/providers/sql-server/functions --- # Function Mappings of the Microsoft SQL Server Provider @@ -11,6 +11,8 @@ This page shows which .NET members are translated into which SQL functions when ## Aggregate functions +For general information about using aggregate functions in queries, see [Aggregate functions](xref:core/querying/complex-query-operators#aggregate-functions). + .NET | SQL | Added in ----------------------------------------------------------------------- | -------------------------------- | -------- EF.Functions.StandardDeviationSample(group.Select(x => x.Property)) | STDEV(Property) diff --git a/entity-framework/core/providers/sqlite/functions.md b/entity-framework/core/providers/sqlite/functions.md index 6725219b68..c0d5b175e3 100644 --- a/entity-framework/core/providers/sqlite/functions.md +++ b/entity-framework/core/providers/sqlite/functions.md @@ -2,7 +2,7 @@ title: Function Mappings - SQLite Database Provider - EF Core description: Function Mappings of the SQLite EF Core database provider author: SamMonoRT -ms.date: 7/26/2023 +ms.date: 08/19/2026 uid: core/providers/sqlite/functions --- # Function Mappings of the SQLite EF Core Provider @@ -11,6 +11,8 @@ This page shows which .NET members are translated into which SQL functions when ## Aggregate functions +For general information about using aggregate functions in queries, see [Aggregate functions](xref:core/querying/complex-query-operators#aggregate-functions). + .NET | SQL | Added in ----------------------------------------------------- | ---------------------------------- | -------- group.Average(x => x.Property) | AVG(Property) diff --git a/entity-framework/core/querying/complex-query-operators.md b/entity-framework/core/querying/complex-query-operators.md index 03f40d829e..b26c344e63 100644 --- a/entity-framework/core/querying/complex-query-operators.md +++ b/entity-framework/core/querying/complex-query-operators.md @@ -2,7 +2,7 @@ title: Complex Query Operators - EF Core description: In-depth information on the more complex LINQ query operators when using Entity Framework Core author: SamMonoRT -ms.date: 10/03/2019 +ms.date: 08/19/2026 uid: core/querying/complex-query-operators --- # Complex Query Operators @@ -114,7 +114,9 @@ HAVING COUNT(*) > 0 ORDER BY [p].[AuthorId] ``` -The aggregate operators EF Core supports are as follows +### Aggregate functions + +Aggregate functions are typically used in the projection after `GroupBy`. Each aggregate produces a scalar value, so the projection can contain both the grouping key and aggregate results. The standard LINQ aggregate operators EF Core supports are as follows: | .NET | SQL | |--------------------------|---------------| @@ -127,6 +129,41 @@ The aggregate operators EF Core supports are as follows Additional aggregate operators may be supported. Check your provider docs for more function mappings. +Some aggregate functions allow their input to be composed. Depending on the provider, `Where` can filter the input, `OrderBy` can specify its ordering, and `Distinct` can remove duplicates. The following query illustrates these shapes: + +```csharp +var query = context.Posts + .GroupBy(p => p.AuthorId) + .Select(g => new + { + g.Key, + Count = g.Count(), + DistinctBlogCount = g.Select(p => p.BlogId).Distinct().Count(), + OrderedTitles = string.Join( + "|", + g.OrderBy(p => p.Title).Select(p => p.Title)), + FilteredTitles = string.Join( + "|", + g.Where(p => p.Rating >= 4).Select(p => p.Title)) + }); +``` + +The supported aggregate functions and compositions vary by provider. Consult the provider's function mappings to determine which forms are translated. + +Standard LINQ aggregate operators have `IQueryable` overloads and can be applied directly to an entire query. Some provider-specific aggregate functions expose only `IEnumerable` overloads and therefore can only be used within a grouping. To apply one of these functions to an entire query, group by a constant: + +```csharp +var standardDeviation = context.Posts + .GroupBy(_ => 1) + .Select(g => EF.Functions.StandardDeviationSample(g.Select(p => p.Rating))) + .FirstOrDefault(); +``` + +The constant creates a single group over the query results. If the source contains no rows, no group is created and `FirstOrDefault` returns the default value. + +> [!NOTE] +> EF Core doesn't currently support mapping user-defined aggregate functions. This is tracked by [issue #27934](https://github.com/dotnet/efcore/issues/27934). + Even though there is no database structure to represent an `IGrouping`, in some cases, EF Core 7.0 and newer can create the groupings after the results are returned from the database. This is similar to how the [`Include`](xref:core/querying/related-data/eager) operator works when including related collections. The following LINQ query uses the GroupBy operator to group the results by the value of their Price property. ```csharp diff --git a/entity-framework/core/querying/user-defined-function-mapping.md b/entity-framework/core/querying/user-defined-function-mapping.md index e76dbd7ef6..bda4bf5a35 100644 --- a/entity-framework/core/querying/user-defined-function-mapping.md +++ b/entity-framework/core/querying/user-defined-function-mapping.md @@ -2,7 +2,7 @@ title: User-defined function mapping - EF Core description: Mapping user-defined functions to database functions author: SamMonoRT -ms.date: 11/23/2020 +ms.date: 08/19/2026 uid: core/querying/user-defined-function-mapping --- # User-defined function mapping @@ -64,6 +64,22 @@ FROM [Blogs] AS [b] WHERE [dbo].[CommentedPostCountForBlog]([b].[BlogId]) > 1 ``` +### Mapping a method to a built-in function + +EF Core considers a mapped function to be user-defined by default. Some databases distinguish built-in and user-defined functions when generating SQL. For example, SQL Server requires user-defined functions to be schema-qualified, but built-in functions aren't schema-qualified. + +Use `IsBuiltIn` to map a CLR method to a built-in function: + +[!code-csharp[Main](../../../samples/core/Querying/UserDefinedFunctionMapping/Model.cs#BuiltInFunctionDefinition)] + +[!code-csharp[Main](../../../samples/core/Querying/UserDefinedFunctionMapping/Model.cs#BuiltInFunctionConfiguration)] + +The property provides the same configuration when using an attribute: + +```csharp +[DbFunction(Name = "ISDATE", IsBuiltIn = true)] +``` + ## Mapping a method to a custom SQL EF Core also allows for user-defined functions that get converted to a specific SQL. The SQL expression is provided using `HasTranslation` method during user-defined function configuration. diff --git a/samples/core/Querying/UserDefinedFunctionMapping/Model.cs b/samples/core/Querying/UserDefinedFunctionMapping/Model.cs index d689449518..c6d0f48d21 100644 --- a/samples/core/Querying/UserDefinedFunctionMapping/Model.cs +++ b/samples/core/Querying/UserDefinedFunctionMapping/Model.cs @@ -53,6 +53,11 @@ public int ActivePostCountForBlog(int blogId) => throw new NotSupportedException(); #endregion + #region BuiltInFunctionDefinition + public static bool IsDate(string value) + => throw new NotSupportedException(); + #endregion + #region HasTranslationFunctionDefinition public double PercentageDifference(double first, int second) => throw new NotSupportedException(); @@ -143,6 +148,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasName("CommentedPostCountForBlog"); #endregion + #region BuiltInFunctionConfiguration + modelBuilder.HasDbFunction(typeof(BloggingContext).GetMethod(nameof(IsDate), [typeof(string)])) + .HasName("ISDATE") + .IsBuiltIn(); + #endregion + #region HasTranslationFunctionConfiguration // 100 * ABS(first - second) / ((first + second) / 2) modelBuilder.HasDbFunction( From 84a277a185e3c9142a9e8df98788b462b4b44817 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Aug 2026 01:10:51 +0000 Subject: [PATCH 3/3] Document ordered SQL Server aggregates Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- entity-framework/core/providers/sql-server/functions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/entity-framework/core/providers/sql-server/functions.md b/entity-framework/core/providers/sql-server/functions.md index 9c00130d5e..a810aad329 100644 --- a/entity-framework/core/providers/sql-server/functions.md +++ b/entity-framework/core/providers/sql-server/functions.md @@ -26,7 +26,9 @@ group.Max(x => x.Property) | MAX(Pr group.Min(x => x.Property) | MIN(Property) group.Sum(x => x.Property) | SUM(Property) string.Concat(group.Select(x => x.Property)) | STRING_AGG(Property, N'') +string.Concat(group.OrderBy(x => x.Other).Select(x => x.Property)) | STRING_AGG(Property, N'') WITHIN GROUP (ORDER BY Other) | EF Core 11.0 string.Join(separator, group.Select(x => x.Property)) | STRING_AGG(Property, @separator) +string.Join(separator, group.OrderBy(x => x.Other).Select(x => x.Property)) | STRING_AGG(Property, @separator) WITHIN GROUP (ORDER BY Other) | EF Core 11.0 ## Binary functions