Pomelo.EntityFrameworkCore.MySql: Incorrect queries generated by Pomelo after migrating from .net core 2.2 to 3.1
Hello, I have been using this library with my Asp.net core 2.2 on a linux server in the past and everything was working fine. Since today we decided to migrate from 2.2 to 3.1 and so we upgraded the Entityframework and also the Pomeleo package as well. I have seen the queries that were working earlier now has stopped working and as of my knowledge the queries are not being generated correcrtly. Linq Query
var query = (
from m in _context.Mail_Accounts
where m.access_type == "Shared" || (m.access_type == "Personal" && m.created_by == ti.UserId)
select new
{
id = m.id,
email = m.email,
unread_count = (from m1 in _context.Mails where m1.is_read == false && m1.incoming == true && m1.mail_account_id == m.id select m1.id).Count(),
folder = (from m2 in _context.Mail_Folders where m2.mail_account_id == m.id && m.is_deleted != true select new { m2.name, m2.id }).FirstOrDefault()
}
).ToList()
Exception:
MySqlException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(
SELECT `m1`.`name`, `m1`.`id`, **1 AS `c`**, `m1`.`mail_account_id`
FROM' at line 6
I don’t know why this is happening or we have to fall back to the old version.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 31
@hazhayder I can confirm, that the MySQL version seems to be in order here, because I can reproduce this issue on my end with MySQL
8.0.18
.To make context use the
ILoggerFactory
instance, you need to modify yourApplicationDbContext
constructor, to include aDbContextOptions<ApplicationDbContext>
parameters:Then, add some additional options, to get more detailed logging output:
With these settings, the following SQL is being logged:
@mguinness You were right, there are global query filters at work here:
This is also evident by the
@__ef_filter___tenant_id_1
parameters shown in the logged query.The query fails with the following exception:
With the query filter removed, the query is simpler, but still fails:
The exception is basically the same:
Looks like MySQL is unable to access the
`c`.`id`
field, though I expect it should be able to, due to the use ofLATERAL
.I reported this issue a while ago on the MySQL Bugtracker as Outer reference in join condition isn’t allowed. Looks like this has been fixed for MySql
8.0.20
.This did not really work in Pomelo 2.2 either. EF Core 2.2 just gave up to translate the query, because it was to complicated and instead switch to client evaluation mode, meaning it just queried all the rows from the database (using multiple simple
SELECT
statements) and then executed the actual query in memory using LINQ. So you got a correct result, but a very inefficient one. You can verify this easily by logging the generated queries for EF Core 2.2.I did check the original query in MySQL
8.0.20
and can confirm that it runs correct there.We could implement a workaround for MySQL versions
8.0.14
to8.0.19
, where theON
clause is always true, and the actual condition is moved to theWHERE
clause. But I am not convinced, that we need to implement this workaround in Pomelo, since anybody affected could just fix this issue by updating MySQL:If you cannot update to MySQL
8.0.20
, you can change your query as follows, by manually applying the workaround I showed above:It generates the following SQL, that should run on MySQL
8.0.18
:Good point!
Yes, being aware about the fact, that the query pipeline was fundamentally rewritten between EF Core 2.2.6 and 3.0.0 is good. But since the query does work generally, as I have proven with the example code above, this is not the issue here.
That was my first though as well. But he is very sure, that he is running the query against a MySQL
8.0.18
server.@hazhayder Here is what you should do next:
_logger
field in the following code contains a constructor injectedILogger<MainController>
instance:If the MySQL version is 8.0.14+, then post the SQL that got logged by EF Core for your failing LINQ query. As @mguinness suggested, you want to enable parameter logging as well. My example code does this too.
Post the code you use to create your
DbContext
, meaning theAddDbContext()
call as well as theDbContext
constructors and theOnConfiguring()
method. This will address @mguinness point, that global query filters might be at work here.