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:
None 
Category:Connector / NET Severity:S1 (Critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any
Tags: Contribution

[29 Nov 2018 9:46] asdfas dfawef
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.
[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
```