private RelationalTypeMapping FindRawMapping(RelationalTypeMappingInfo mappingInfo)
        {
            // Use deferred initialization to support connection (string) based type mapping in
            // design time mode (scaffolder etc.).
            if (!_initialized)
            {
                Initialize();
                _initialized = true;
            }

            var clrType           = mappingInfo.ClrType;
            var storeTypeName     = mappingInfo.StoreTypeName;
            var storeTypeNameBase = mappingInfo.StoreTypeNameBase;

            if (storeTypeName != null)
            {
                if (_options.DefaultDataTypeMappings.ClrBoolean != MySqlBooleanType.None)
                {
                    if (_options.DefaultDataTypeMappings.ClrBoolean == MySqlBooleanType.Bit1)
                    {
                        if (storeTypeName.Equals(_bit1.StoreType, StringComparison.OrdinalIgnoreCase))
                        {
                            return(_bit1);
                        }
                    }
                    else
                    {
                        if (storeTypeName.Equals(_tinyint1.StoreType, StringComparison.OrdinalIgnoreCase))
                        {
                            return(_tinyint1);
                        }
                    }
                }

                if (MySqlGuidTypeMapping.IsValidGuidFormat(_options.ConnectionSettings.GuidFormat))
                {
                    if (storeTypeName.Equals(_guid.StoreType, StringComparison.OrdinalIgnoreCase) &&
                        (clrType == typeof(Guid) || clrType == null))
                    {
                        return(_guid);
                    }
                }

                if (storeTypeNameBase.Equals(_dateTime6.StoreTypeNameBase, StringComparison.OrdinalIgnoreCase))
                {
                    if (clrType == null ||
                        clrType == typeof(DateTime))
                    {
                        if (mappingInfo.Precision.GetValueOrDefault() > 0 ||
                            _options.ServerVersion.SupportsDateTime6 && _options.DefaultDataTypeMappings.ClrDateTime != MySqlDateTimeType.DateTime)
                        {
                            return(_dateTime6);
                        }
                        else
                        {
                            return(_dateTime);
                        }
                    }

                    if (clrType == typeof(DateTimeOffset))
                    {
                        if (mappingInfo.Precision.GetValueOrDefault() > 0 ||
                            _options.ServerVersion.SupportsDateTime6 && _options.DefaultDataTypeMappings.ClrDateTimeOffset != MySqlDateTimeType.DateTime)
                        {
                            return(_dateTimeOffset6);
                        }
                        else
                        {
                            return(_dateTimeOffset);
                        }
                    }
                }
                else if (storeTypeNameBase.Equals(_timeStamp6.StoreTypeNameBase, StringComparison.OrdinalIgnoreCase))
                {
                    if (clrType == null ||
                        clrType == typeof(DateTime))
                    {
                        return(_timeStamp6);
                    }

                    if (clrType == typeof(DateTimeOffset))
                    {
                        return(_timeStampOffset6);
                    }
                }

                if (_storeTypeMappings.TryGetValue(storeTypeName, out var mapping) ||
                    _storeTypeMappings.TryGetValue(storeTypeNameBase, out mapping))
                {
                    return(clrType == null ||
                           mapping.ClrType == clrType
                        ? mapping
                        : null);
                }
            }

            if (clrType != null)
            {
                if (_clrTypeMappings.TryGetValue(clrType, out var mapping))
                {
                    return(mapping);
                }

                if (clrType.TryGetElementType(typeof(JsonObject <>)) != null)
                {
                    return(new MySqlJsonTypeMapping(clrType, unicode: mappingInfo.IsUnicode));
                }

                if (clrType == typeof(string))
                {
                    // Some of this logic could be moved into MySqlStringTypeMapping once EF #11896 is fixed
                    var isNationalCharSet = storeTypeNameBase != null &&
                                            (storeTypeNameBase.Equals(_nchar.StoreTypeNameBase, StringComparison.OrdinalIgnoreCase) ||
                                             storeTypeNameBase.Equals(_nvarchar.StoreTypeNameBase, StringComparison.OrdinalIgnoreCase));
                    var isFixedLength = mappingInfo.IsFixedLength == true;
                    var charset       = isNationalCharSet ? _options.NationalCharSet : _options.CharSet;
                    var isUnicode     = mappingInfo.IsUnicode ?? charset.IsUnicode;
                    var bytesPerChar  = charset.MaxBytesPerChar;
                    var charSetSuffix = string.Empty;

                    if (isUnicode &&
                        (mappingInfo.IsKeyOrIndex &&
                         (_options.CharSetBehavior & CharSetBehavior.AppendToUnicodeIndexAndKeyColumns) != 0 ||
                         !mappingInfo.IsKeyOrIndex &&
                         (_options.CharSetBehavior & CharSetBehavior.AppendToUnicodeNonIndexAndKeyColumns) != 0) ||
                        !isUnicode &&
                        (mappingInfo.IsKeyOrIndex &&
                         (_options.CharSetBehavior & CharSetBehavior.AppendToAnsiIndexAndKeyColumns) != 0 ||
                         !mappingInfo.IsKeyOrIndex &&
                         (_options.CharSetBehavior & CharSetBehavior.AppendToAnsiNonIndexAndKeyColumns) != 0))
                    {
                        charSetSuffix = $" CHARACTER SET {(isNationalCharSet ? _options.NationalCharSet : _options.CharSet).Name}";
                    }

                    var maxSize = 8000 / bytesPerChar;

                    var size = mappingInfo.Size ??
                               (mappingInfo.IsKeyOrIndex
                                // Allow to use at most half of the max key length, so at least 2 columns can fit
                                   ? Math.Min(_options.ServerVersion.MaxKeyLength / (bytesPerChar * 2), 255)
                                   : (int?)null);
                    if (size > maxSize)
                    {
                        size = null;
                    }

                    var dbType = isUnicode
                        ? isFixedLength ? DbType.StringFixedLength : DbType.String
                        : isFixedLength ? DbType.AnsiStringFixedLength : DbType.AnsiString;

                    return(new MySqlStringTypeMapping(
                               size == null
                            ? "longtext" + charSetSuffix
                            : (isNationalCharSet ? "n" : string.Empty) +
                               (isFixedLength ? "char(" : "varchar(") + size + ")" + charSetSuffix,
                               dbType,
                               _options,
                               isUnicode,
                               size,
                               isFixedLength));
                }

                if (clrType == typeof(byte[]))
                {
                    if (mappingInfo.IsRowVersion == true)
                    {
                        return(_options.ServerVersion.SupportsDateTime6
                            ? _binaryRowVersion6
                            : _binaryRowVersion);
                    }

                    var size = mappingInfo.Size ??
                               (mappingInfo.IsKeyOrIndex ? _options.ServerVersion.MaxKeyLength : (int?)null);

                    return(new MySqlByteArrayTypeMapping(
                               size: size,
                               fixedLength: mappingInfo.IsFixedLength == true));
                }

                if (_scaffoldingClrTypeMappings.TryGetValue(clrType, out mapping))
                {
                    return(mapping);
                }
            }

            return(null);
        }
        private void Initialize()
        {
            //
            // String mappings depend on the MySqlOptions.NoBackslashEscapes setting:
            //

            _charUnicode       = new MySqlStringTypeMapping("char", DbType.StringFixedLength, _options, fixedLength: true);
            _varcharUnicode    = new MySqlStringTypeMapping("varchar", DbType.String, _options);
            _tinytextUnicode   = new MySqlStringTypeMapping("tinytext", DbType.String, _options);
            _textUnicode       = new MySqlStringTypeMapping("text", DbType.String, _options);
            _mediumtextUnicode = new MySqlStringTypeMapping("mediumtext", DbType.String, _options);
            _longtextUnicode   = new MySqlStringTypeMapping("longtext", DbType.String, _options);

            _nchar    = new MySqlStringTypeMapping("nchar", DbType.StringFixedLength, _options, fixedLength: true);
            _nvarchar = new MySqlStringTypeMapping("nvarchar", DbType.String, _options);

            _enum = new MySqlStringTypeMapping("enum", DbType.String, _options);

            _guid = MySqlGuidTypeMapping.IsValidGuidFormat(_options.ConnectionSettings.GuidFormat)
                ? new MySqlGuidTypeMapping(_options.ConnectionSettings.GuidFormat)
                : null;

            _storeTypeMappings
                = new Dictionary <string, RelationalTypeMapping[]>(StringComparer.OrdinalIgnoreCase)
                {
                // bit
                { "bit", new[] { _bit } },

                // integers
                { "tinyint", new[] { _tinyint } },
                { "tinyint unsigned", new[] { _utinyint } },
                { "smallint", new[] { _smallint } },
                { "smallint unsigned", new[] { _usmallint } },
                { "mediumint", new[] { _int } },
                { "mediumint unsigned", new[] { _uint } },
                { "int", new[] { _int } },
                { "int unsigned", new[] { _uint } },
                { "integer", new[] { _int } },
                { "integer unsigned", new[] { _uint } },
                { "bigint", new[] { _bigint } },
                { "bigint unsigned", new[] { _ubigint } },

                // decimals
                { "decimal", new[] { _decimal } },
                { "decimal unsigned", new[] { _decimal } },            // deprecated since 8.0.17-mysql
                { "numeric", new[] { _decimal } },
                { "numeric unsigned", new[] { _decimal } },            // deprecated since 8.0.17-mysql
                { "dec", new[] { _decimal } },
                { "dec unsigned", new[] { _decimal } },                // deprecated since 8.0.17-mysql
                { "fixed", new[] { _decimal } },
                { "fixed unsigned", new[] { _decimal } },              // deprecated since 8.0.17-mysql
                { "double", new[] { _double } },
                { "double unsigned", new[] { _double } },              // deprecated since 8.0.17-mysql
                { "double precision", new[] { _double } },
                { "double precision unsigned", new[] { _double } },    // deprecated since 8.0.17-mysql
                { "real", new[] { _double } },
                { "real unsigned", new[] { _double } },                // deprecated since 8.0.17-mysql
                { "float", new[] { _float } },
                { "float unsigned", new[] { _float } },                // deprecated since 8.0.17-mysql

                // binary
                { "binary", new[] { _binary } },
                { "varbinary", new[] { _varbinary } },
                { "tinyblob", new[] { _varbinary } },
                { "blob", new[] { _varbinary } },
                { "mediumblob", new[] { _varbinary } },
                { "longblob", new[] { _varbinary } },

                // string
                { "char", new[] { _charUnicode } },
                { "varchar", new[] { _varcharUnicode } },
                { "tinytext", new[] { _tinytextUnicode } },
                { "text", new[] { _textUnicode } },
                { "mediumtext", new[] { _mediumtextUnicode } },
                { "longtext", new[] { _longtextUnicode } },

                { "enum", new[] { _enum } },

                { "nchar", new[] { _nchar } },
                { "nvarchar", new[] { _nvarchar } },

                // DateTime
                { "year", new[] { _year } },
                { "date", new[] { _date } },
                { "time", new[] { _time } },
                { "datetime", new RelationalTypeMapping[] { _dateTime, _dateTimeOffset } },
                { "timestamp", new RelationalTypeMapping[] { _timeStamp, _timeStampOffset } },
                };

            _clrTypeMappings
                = new Dictionary <Type, RelationalTypeMapping>
                {
                // integers
                { typeof(short), _smallint },
        protected void Initialize()
        {
            //
            // String mappings depend on the MySqlOptions.NoBackslashEscapes setting:
            //

            _charUnicode       = new MySqlStringTypeMapping("char", DbType.StringFixedLength, _options, unicode: true, fixedLength: true);
            _varcharUnicode    = new MySqlStringTypeMapping("varchar", DbType.String, _options, unicode: true);
            _varcharmaxUnicode = new MySqlStringTypeMapping("longtext", DbType.String, _options, unicode: true);

            _nchar    = new MySqlStringTypeMapping("nchar", DbType.StringFixedLength, _options, unicode: true, fixedLength: true);
            _nvarchar = new MySqlStringTypeMapping("nvarchar", DbType.String, _options, unicode: true);

            _enum = new MySqlStringTypeMapping("enum", DbType.String, _options, unicode: true);

            _guid = MySqlGuidTypeMapping.IsValidGuidFormat(_options.ConnectionSettings.GuidFormat)
                ? new MySqlGuidTypeMapping(_options.ConnectionSettings.GuidFormat)
                : null;

            _storeTypeMappings
                = new Dictionary <string, RelationalTypeMapping>(StringComparer.OrdinalIgnoreCase)
                {
                // bit
                { "bit", _bit },

                // integers
                { "tinyint", _tinyint },
                { "tinyint unsigned", _utinyint },
                { "smallint", _smallint },
                { "smallint unsigned", _usmallint },
                { "mediumint", _int },
                { "mediumint unsigned", _uint },
                { "int", _int },
                { "int unsigned", _uint },
                { "integer", _int },
                { "integer unsigned", _uint },
                { "bigint", _bigint },
                { "bigint unsigned", _ubigint },

                // decimals
                { "decimal", _decimal },
                { "decimal unsigned", _decimal },         // deprecated since 8.0.17-mysql
                { "numeric", _decimal },
                { "numeric unsigned", _decimal },         // deprecated since 8.0.17-mysql
                { "dec", _decimal },
                { "dec unsigned", _decimal },             // deprecated since 8.0.17-mysql
                { "fixed", _decimal },
                { "fixed unsigned", _decimal },           // deprecated since 8.0.17-mysql
                { "double", _double },
                { "double unsigned", _double },           // deprecated since 8.0.17-mysql
                { "double precision", _double },
                { "double precision unsigned", _double }, // deprecated since 8.0.17-mysql
                { "real", _double },
                { "real unsigned", _double },             // deprecated since 8.0.17-mysql
                { "float", _float },
                { "float unsigned", _float },             // deprecated since 8.0.17-mysql

                // binary
                { "binary", _binary },
                { "varbinary", _varbinary },
                { "tinyblob", _varbinary },
                { "blob", _varbinary },
                { "mediumblob", _varbinary },
                { "longblob", _varbinary },

                // string
                { "char", _charUnicode },
                { "varchar", _varcharUnicode },
                { "tinytext", _varcharmaxUnicode },
                { "text", _varcharmaxUnicode },
                { "mediumtext", _varcharmaxUnicode },
                { "longtext", _varcharmaxUnicode },

                { "enum", _enum },

                { "nchar", _nchar },
                { "nvarchar", _nvarchar },

                // DateTime
                { "date", _date }
                };

            _clrTypeMappings
                = new Dictionary <Type, RelationalTypeMapping>
                {
                // integers
                { typeof(short), _smallint },
                { typeof(ushort), _usmallint },
                { typeof(int), _int },
                { typeof(uint), _uint },
                { typeof(long), _bigint },
                { typeof(ulong), _ubigint },

                // decimals
                { typeof(decimal), _decimal },
                { typeof(float), _float },
                { typeof(double), _double },

                // byte / char
                { typeof(sbyte), _tinyint },
                { typeof(byte), _utinyint },
                };

            // Boolean
            if (_options.DefaultDataTypeMappings.ClrBoolean != MySqlBooleanType.None)
            {
                _clrTypeMappings[typeof(bool)] = _options.DefaultDataTypeMappings.ClrBoolean == MySqlBooleanType.Bit1
                    ? _bit1
                    : _tinyint1;
            }

            // DateTime
            _storeTypeMappings["time"] = !_options.ServerVersion.SupportsDateTime6 ||
                                         _options.DefaultDataTypeMappings.ClrTimeSpan == MySqlTimeSpanType.Time
                ? _time
                : _time6;

            _clrTypeMappings[typeof(TimeSpan)] = !_options.ServerVersion.SupportsDateTime6 ||
                                                 _options.DefaultDataTypeMappings.ClrTimeSpan == MySqlTimeSpanType.Time
                ? _time
                : _time6;

            _clrTypeMappings[typeof(DateTime)] = !_options.ServerVersion.SupportsDateTime6 ||
                                                 _options.DefaultDataTypeMappings.ClrDateTime == MySqlDateTimeType.DateTime
                ? _dateTime
                : _options.DefaultDataTypeMappings.ClrDateTime == MySqlDateTimeType.Timestamp6
                    ? _timeStamp6
                    : _dateTime6;

            _clrTypeMappings[typeof(DateTimeOffset)] = !_options.ServerVersion.SupportsDateTime6 ||
                                                       _options.DefaultDataTypeMappings.ClrDateTime == MySqlDateTimeType.DateTime
                ? _dateTimeOffset
                : _options.DefaultDataTypeMappings.ClrDateTimeOffset == MySqlDateTimeType.Timestamp6
                    ? _timeStampOffset6
                    : _dateTimeOffset6;

            // Guid
            if (_guid != null)
            {
                _clrTypeMappings[typeof(Guid)] = _guid;
            }

            // Type mappings that only exist to work around the limited code generation capabilites when scaffolding:
            _scaffoldingClrTypeMappings = new Dictionary <Type, RelationalTypeMapping>
            {
                { typeof(MySqlCodeGenerationMemberAccess), _codeGenerationMemberAccess }
            };
        }