diff --git a/.gitignore b/.gitignore
index 1ceed1dc6..63be1f19e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -338,3 +338,6 @@ ASALocalRun/
# Local History for Visual Studio
.localhistory/
+
+#VSCode
+.vscode/
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 476b30e9f..ad071dfb6 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,16 +1,21 @@
{
- "version": "0.1.0",
+ "version": "2.0.0",
"command": "dotnet",
- "isShellCommand": true,
"args": [],
"tasks": [
{
- "taskName": "build",
+ "label": "build",
+ "type": "shell",
+ "command": "dotnet",
"args": [
+ "build",
"${workspaceRoot}/test/EFCore.MySql.IntegrationTests/EFCore.MySql.IntegrationTests.csproj"
],
- "isBuildCommand": true,
- "problemMatcher": "$msCompile"
+ "problemMatcher": "$msCompile",
+ "group": {
+ "_id": "build",
+ "isDefault": false
+ }
}
]
}
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index c4e17801f..84844f410 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -5,19 +5,15 @@
-->
[9.0.0,9.0.999]
-
-
+
-
-
+
-
-
-
-
+
+
@@ -28,19 +24,19 @@
-
-
+
+
+
-
+
-
@@ -48,7 +44,6 @@
-
diff --git a/global.json b/global.json
index db8627a23..2793da572 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "9.0.100",
+ "version": "10.0.103",
"allowPrerelease": false,
"rollForward": "latestFeature"
}
diff --git a/src/EFCore.MySql/Query/ExpressionVisitors/Internal/MySqlQuerySqlGenerator.cs b/src/EFCore.MySql/Query/ExpressionVisitors/Internal/MySqlQuerySqlGenerator.cs
index c86ad0e9e..610d61804 100644
--- a/src/EFCore.MySql/Query/ExpressionVisitors/Internal/MySqlQuerySqlGenerator.cs
+++ b/src/EFCore.MySql/Query/ExpressionVisitors/Internal/MySqlQuerySqlGenerator.cs
@@ -249,6 +249,14 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression)
}
}
+ // Single-argument aggregates: generate Name(arg) to match historical SQL shape.
+ // EF Core 9.x base now generates Name((arg)); we keep the old format for backward compatibility.
+ private static readonly HashSet SingleArgAggregateFunctions = new(StringComparer.OrdinalIgnoreCase)
+ {
+ "AVG", "MAX", "MIN", "SUM", "COUNT", "BIT_AND", "BIT_OR", "BIT_XOR",
+ "STD", "STDDEV", "STDDEV_POP", "STDDEV_SAMP", "VAR_POP", "VAR_SAMP", "VARIANCE",
+ };
+
protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression)
{
if (sqlFunctionExpression.Name.StartsWith("@@", StringComparison.Ordinal))
@@ -258,6 +266,16 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction
return sqlFunctionExpression;
}
+ if (SingleArgAggregateFunctions.Contains(sqlFunctionExpression.Name)
+ && sqlFunctionExpression.Arguments.Count == 1)
+ {
+ Sql.Append(sqlFunctionExpression.Name);
+ Sql.Append("(");
+ Visit(sqlFunctionExpression.Arguments[0]);
+ Sql.Append(")");
+ return sqlFunctionExpression;
+ }
+
return base.VisitSqlFunction(sqlFunctionExpression);
}
diff --git a/test/EFCore.MySql.FunctionalTests/Query/EscapesMySqlTestBase.cs b/test/EFCore.MySql.FunctionalTests/Query/EscapesMySqlTestBase.cs
index ac08eae8d..d6698fcac 100644
--- a/test/EFCore.MySql.FunctionalTests/Query/EscapesMySqlTestBase.cs
+++ b/test/EFCore.MySql.FunctionalTests/Query/EscapesMySqlTestBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -84,7 +84,9 @@ public virtual async Task Where_contains_query_escapes(bool async)
{
using (var context = CreateContext())
{
- var artistNames = new[]
+ // Use List so Contains binds to Enumerable.Contains; array can bind to
+ // MemoryExtensions.Contains(ReadOnlySpan) and break the expression interpreter.
+ var artistNames = new List
{
@"Back\slasher's",
@"John's Chill Box"
diff --git a/test/EFCore.MySql.FunctionalTests/Query/GearsOfWarQueryMySqlTest.cs b/test/EFCore.MySql.FunctionalTests/Query/GearsOfWarQueryMySqlTest.cs
index 081add88c..dcdd0b4ef 100644
--- a/test/EFCore.MySql.FunctionalTests/Query/GearsOfWarQueryMySqlTest.cs
+++ b/test/EFCore.MySql.FunctionalTests/Query/GearsOfWarQueryMySqlTest.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
@@ -26,7 +27,8 @@ public override Task DateTimeOffset_Contains_Less_than_Greater_than(bool async)
var dto = MySqlTestHelpers.GetExpectedValue(new DateTimeOffset(599898024001234567, new TimeSpan(1, 30, 0)));
var start = dto.AddDays(-1);
var end = dto.AddDays(1);
- var dates = new[] { dto };
+ // Use List to avoid ReadOnlySpan in expression tree (same as EscapesMySqlTestBase).
+ var dates = new List { dto };
return AssertQuery(
async,
diff --git a/test/EFCore.MySql.FunctionalTests/Query/TPCGearsOfWarQueryMySqlTest.cs b/test/EFCore.MySql.FunctionalTests/Query/TPCGearsOfWarQueryMySqlTest.cs
index e94bd2631..b29a2880e 100644
--- a/test/EFCore.MySql.FunctionalTests/Query/TPCGearsOfWarQueryMySqlTest.cs
+++ b/test/EFCore.MySql.FunctionalTests/Query/TPCGearsOfWarQueryMySqlTest.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
@@ -9147,7 +9148,8 @@ public override async Task DateTimeOffset_Contains_Less_than_Greater_than(bool a
var dto = MySqlTestHelpers.GetExpectedValue(new DateTimeOffset(599898024001234567, new TimeSpan(1, 30, 0)));
var start = dto.AddDays(-1);
var end = dto.AddDays(1);
- var dates = new[] { dto };
+ // Use List to avoid ReadOnlySpan in expression tree (same as GearsOfWarQueryMySqlTest).
+ var dates = new List { dto };
await AssertQuery(
async,
diff --git a/test/EFCore.MySql.FunctionalTests/Query/TPTGearsOfWarQueryMySqlTest.cs b/test/EFCore.MySql.FunctionalTests/Query/TPTGearsOfWarQueryMySqlTest.cs
index a0a91e103..75f8e3abf 100644
--- a/test/EFCore.MySql.FunctionalTests/Query/TPTGearsOfWarQueryMySqlTest.cs
+++ b/test/EFCore.MySql.FunctionalTests/Query/TPTGearsOfWarQueryMySqlTest.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
@@ -28,7 +29,8 @@ public override Task DateTimeOffset_Contains_Less_than_Greater_than(bool async)
var dto = MySqlTestHelpers.GetExpectedValue(new DateTimeOffset(599898024001234567, new TimeSpan(1, 30, 0)));
var start = dto.AddDays(-1);
var end = dto.AddDays(1);
- var dates = new[] { dto };
+ // Use List to avoid ReadOnlySpan in expression tree (same as GearsOfWarQueryMySqlTest).
+ var dates = new List { dto };
return AssertQuery(
async,
diff --git a/test/EFCore.MySql.FunctionalTests/README.md b/test/EFCore.MySql.FunctionalTests/README.md
index b50af38b1..813b87d56 100644
--- a/test/EFCore.MySql.FunctionalTests/README.md
+++ b/test/EFCore.MySql.FunctionalTests/README.md
@@ -3,6 +3,8 @@ Functional Tests
**Configuring the Database**
+The functional tests are intended to be run against **MySQL 8.0+** or an equivalent **MariaDB** version (see the main README for tested versions).
+
Configure your MySQL database by opening the `config.json.example` file, specifying the connection string and saving the changed file as `config.json`.
**Running Functional Tests**
diff --git a/test/EFCore.MySql.IntegrationTests/README.md b/test/EFCore.MySql.IntegrationTests/README.md
index bd67efbc4..194f58e97 100644
--- a/test/EFCore.MySql.IntegrationTests/README.md
+++ b/test/EFCore.MySql.IntegrationTests/README.md
@@ -3,6 +3,8 @@ Integration and Performance Tests
**Configuring the Database**
+The integration tests are intended to be run against **MySQL 8.0+** or an equivalent **MariaDB** version (see the main README for tested versions).
+
1. Configure your MySQL database by opening the `config.json.example` file, specifying the connection string and saving the changed file as `config.json`.
2. Run the `scripts/rebuild.ps1` PowerShell script on Linux or Windows to rebuild all migrations (for installing PowerShell, see [Install PowerShell on Windows, Linux, and macOS](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)). Any time you make changes to the database models, run the rebuild script again.