Bug #93398 Can't filter with Contains in EntityFrameworkCore for Guid or Byte[] fields
| Submitted: | 29 Nov 2018 9:46 | Modified: | 22 Feb 2021 20:16 |
|---|---|---|---|
| Reporter: | asdfas dfawef | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / NET | Severity: | S1 (Critical) |
| Version: | 8.0 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | Contribution | ||
[29 Nov 2018 13:57]
asdfas dfawef
I've written a PR to fix the issue: https://github.com/mysql/mysql-connector-net/pull/27 However, I found that if I used OldGuids=True, I couldn't read the data, with the error: System.InvalidOperationException: An exception occurred while reading a database value for property 'Testtable.Uuid'. The expected type was 'System.Guid' but the actual value was of type 'System.Guid'. ---> System.InvalidCastException: Unable to cast object of type 'System.Guid' to type 'System.Guid'. at System.Data.Common.DbDataReader.GetFieldValue[T](Int32 ordinal) at MySql.Data.MySqlClient.MySqlDataReader.GetFieldValue[T](Int32 ordinal) at lambda_method(Closure , DbDataReader ) --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityMaterializerSource.ThrowReadValueException[TValue](Exception exception, Object value, IPropertyBase property) at lambda_method(Closure , DbDataReader ) at Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items) at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) So for now I removed the OldGuids=True and it works, I hope it won't affect my data. Please accept this PR! Thanks.
[5 Dec 2018 12:12]
MySQL Verification Team
Thank you for the report. I see you have already submitted this pull request - https://github.com/mysql/mysql-connector-net/pull/27 Have you signed and submitted OCA? Please note that in order to submit contributions you must first sign the Oracle Contribution Agreement (OCA). For additional information please check http://www.oracle.com/technetwork/community/oca-486395.html. If you have any questions, please contact the MySQL community team - https://dev.mysql.com/community/ Once OCA is in place then you can attach patch using the "contribution" tab to this bug report. regards, Umesh
[6 Jan 2019 1:00]
Bugs System
No feedback was provided for this bug for over a month, so it is being suspended automatically. If you are able to provide the information that was originally requested, please do so and change the status of the bug back to "Open".
[19 Nov 2020 4:38]
MySQL Verification Team
Hello! Thank you for the report and contribution. regards, Umesh
[22 Feb 2021 20:16]
Christine Cole
Posted by developer: Fixed as of the upcoming MySQL Connector/NET 8.0.24 release, and here's the proposed changelog entry from the documentation team: Incomplete GUID mapping in Entity Framework Core caused an error when the Contains method was used to filter records. Thank you for the bug report.
[12 Oct 2021 2:52]
David Swanson
Hi, I am still having the same exact issue as described here. I am using nuget package MySql.EntityFrameworkCore 5.0.5+MySQL8.0.26 published: Tuesday, July 20, 2021. Any information would be very appreciated. Thanks
[4 Apr 2022 8:59]
Robert Schmidt
This is still an issue on EF Core 6.0 with MySQL.Data 8.0.28. Given the BINARY(32) column Operations.Hash and ``` IEnumerable<byte[]> hashes; ``` then both ``` source.Where(o => hashes.Any(h => o.Hash == h)) ``` and ``` source.Where(o => hashes.Contains(o.Hash)) ``` are both injecting the literal string "System.Byte[]" into the generated SQL: ``` SELECT `o`.`Hash`, `o`.`Id` FROM `Operations` AS `o` WHERE `o`.`Hash` = System.Byte[] ``` causing ``` MySqlException (0x80004005): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '[]' at line 3 ```
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.058 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.
Description: When having a column of type binary(16) and the EntityFrameworkCore type is Guid or Byte[], we can't use the Contains extension to filter the records. We have tested it on dotnet core 2.1 with the MySql.EntityFrameworkCore 8.0.13. How to repeat: Create a table: CREATE TABLE `testtable` ( `id` int(11) NOT NULL, `uuid` binary(16) NOT NULL, PRIMARY KEY (`id`) ); Create an entity in C#: public class Testtable { public int Id { get; set; } public Guid Uuid { get; set; } } Create a context: public class MyContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseMySQL("server=localhost;user id=myuser;password=mypassword;database=testdb;persistsecurityinfo=True;Charset=utf8mb4;old guids=True;"); } } ... protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Testtable>(entity => { entity.HasKey(e => e.Id); entity.ToTable("testtable"); entity.Property(e => e.Id) .HasColumnName("id") .HasColumnType("int(11)"); entity.Property(e => e.Uuid) .HasColumnName("uuid") .HasColumnType("binary(16)"); }); } } Now select a contains: var filter = new [] { Guid.Empty }; var context = new MyContext(); var resultFilter = context.TesttableSet.Where(t => filter.Contains(t.Uuid)).ToArray(); This will result in the following exception: MySql.Data.MySqlClient.MySqlException (0x80004005): 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 '[])' at line 3 at MySql.Data.MySqlClient.MySqlStream.ReadPacket() at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId) at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force) at MySql.Data.MySqlClient.MySqlDataReader.NextResult() at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader() at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items) at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source) This is because when checking the executed SQL will result in something along the lines of: SELECT ... FROM `testtable` WHERE uuid IN (System.Byte[]) Suggested fix: Please fix the contains extension to work as it should and as it worked in older versions.