Comments (3)
It would probably be better if UpdateAndSelectSqlGenerator.AppendWhereAffectedClause() would explicitly throw in cases where there is no clause generated after the AND keyword has already been appended.
@lauxjpn can you open an issue on this with the problematic case etc.? Of course a PR is always welcome too.
from pomelo.entityframeworkcore.mysql.
For EF Core to track your newly inserted entity, it needs to either know the ID of the entity in advance, or it needs a mechanism to read it back from the database, after it was generate by the database (which can be done for regular integer IDs with LAST_INSERT_ID()
).
Since there is no way for EF Core or Pomelo to reliably read back the ID value generated by the (UUID_TO_BIN(UUID(), 1))
default value expression, because it generates the ID that EF Core/Pomelo would already need to know to read it back, your code cannot work in the way you intend it to.
What you would want to do instead is to let EF Core/Pomelo generate a Guid
for the entity when generating the INSERT INTO
statement, which is what we do by default, as long as you don't specify a default value expression or explicitly disable it. The Guid
we generate is also index optimized (see MySqlSequentialGuidValueGenerator):
Program.cs
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MySqlConnector;
namespace IssueConsoleTemplate;
public class IceCream
{
public Guid IceCreamId { get; set; }
public string Name { get; set; }
}
public class Context : DbContext
{
public DbSet<IceCream> IceCreams { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var connectionString = new MySqlConnectionStringBuilder("server=127.0.0.1;port=3306;user=root;password=;Database=Issue1909")
{
GuidFormat = MySqlGuidFormat.Binary16
}.ConnectionString;
var serverVersion = ServerVersion.AutoDetect(connectionString);
optionsBuilder
.UseMySql(connectionString, serverVersion)
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IceCream>(
entity =>
{
// This cannot not work:
// entity.Property(e => e.IceCreamId)
// .HasDefaultValueSql("(UUID_TO_BIN(UUID()))");
});
}
}
internal static class Program
{
private static void Main()
{
using var context = new Context();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
context.IceCreams.Add(new IceCream { Name = "Vanilla" });
context.SaveChanges();
var result = context.IceCreams.Single();
Trace.Assert(result.IceCreamId != Guid.Empty);
Trace.Assert(result.Name == "Vanilla");
}
}
Output (SQL)
warn: 25.04.2024 13:19:54.044 CoreEventId.SensitiveDataLoggingEnabledWarning[10400] (Microsoft.EntityFrameworkCore.Infrastructure)
Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.
info: 25.04.2024 13:19:54.374 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (25ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
DROP DATABASE `Issue1909`;
info: 25.04.2024 13:20:01.529 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE DATABASE `Issue1909`;
info: 25.04.2024 13:20:01.649 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER DATABASE CHARACTER SET utf8mb4;
info: 25.04.2024 13:20:01.680 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (30ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE `IceCreams` (
`IceCreamId` binary(16) NOT NULL,
`Name` longtext CHARACTER SET utf8mb4 NULL,
CONSTRAINT `PK_IceCreams` PRIMARY KEY (`IceCreamId`)
) CHARACTER SET=utf8mb4;
info: 25.04.2024 13:20:01.861 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (22ms) [Parameters=[@p0='08dc6519-a639-4aa6-8942-389cc7b7666a', @p1='Vanilla' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET AUTOCOMMIT = 1;
INSERT INTO `IceCreams` (`IceCreamId`, `Name`)
VALUES (@p0, @p1);
info: 25.04.2024 13:20:02.099 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT `i`.`IceCreamId`, `i`.`Name`
FROM `IceCreams` AS `i`
LIMIT 2
@ajcvickers It would probably be better if UpdateAndSelectSqlGenerator.AppendWhereAffectedClause()
would explicitly throw in cases where there is no clause generated after the AND
keyword has already been appended.
from pomelo.entityframeworkcore.mysql.
Understood. I figured EFCore would have been able to track all entities and their relationships via the temporary IDs, and have them respectively populated once DbContext.SaveChangesAsync()
was called and assumed this was a seperate issue with the query generator (you know what they say about assumptions).
The
Guid
we generate is also index optimized (see MySqlSequentialGuidValueGenerator)
Apologies for my original incorrect conclusion that the generated ID was not index-safe. This is good to know, and will prove a perfect alternative to UUID_TO_BIN(UUID(), 1)
. As much as I would love my database be the only thing that generates IDs, this is a valid compromise.
I will leave this issue open in case of any further discourse, however I would consider it resolved from my end of things. Thank you!
from pomelo.entityframeworkcore.mysql.
Related Issues (20)
- ArgumentException: Option 'name' not supported. HOT 11
- Input string was not in a correct format when compare with TimeSpan HOT 1
- After upgrading from 7.0.0 to 8.0.2, SQL translation results are changed and this version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'. HOT 4
- MySQL operations break after InvalidOperationException: Can't Replace Active Reader HOT 2
- Remove explicit reference to `System.Text.Json` package from `Pomelo.EntityFrameworkCore.MySql.Json.Microsoft` package HOT 4
- After upgrading to 8.0.2 .SetAfterSaveBehavior(PropertySaveBehavior.Ignore) generates SQL that updates the column value HOT 7
- TimeSpan.TotalHours could not be translated HOT 7
- Error assigning index for [table] HOT 1
- Error adding integer auto-increment column with migration (since 8.0.1)
- System.TypeLoadException: Method 'Quote' in type does not have an implementation. HOT 1
- MariaDB Maxscale Support
- DbContext.Database.Migrate() change guid charset and Collation
- ExecuteDeleteAsync in combination with Take throws InvalidOperationException
- Unnecessary migration is generated after update to 8.0.2 HOT 5
- Custom value conversion fails for byte[] property to GEOMETRY SQL column. HOT 1
- Query for List<string> property could not be translated
- Insertion failed after upgrading .net 6 to .net8
- When use `Min Pool Size = 10` app hangs due to connection timeout HOT 1
- MySQL 8.4.0 error prompt Plugin' mysqlnotative_password 'is not loaded
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pomelo.entityframeworkcore.mysql.