internal TypeHandler this[NpgsqlDbType npgsqlDbType, Type specificType = null] { get { if (specificType != null && (npgsqlDbType & NpgsqlDbType.Enum) == 0 && (npgsqlDbType & NpgsqlDbType.Composite) == 0) { throw new ArgumentException($"{nameof(specificType)} can only be used with {nameof(NpgsqlDbType.Enum)} or {nameof(NpgsqlDbType.Composite)}"); } TypeHandler handler; if (ByNpgsqlDbType.TryGetValue(npgsqlDbType, out handler)) { return(handler); } if (specificType != null) // Enum/composite { // Note that enums and composites are never lazily activated - they're activated at the // moment of mapping (or at connection time when globally-mapped) if ((npgsqlDbType & NpgsqlDbType.Array) != 0) { // Already-activated array of enum/composite if (ArrayHandlerByType != null && ArrayHandlerByType.TryGetValue(specificType, out handler)) { return(handler); } } // For non-array enum/composite, simply delegate to type inference return(this[specificType]); } // Couldn't find already activated type, attempt to activate if (npgsqlDbType == NpgsqlDbType.Enum || npgsqlDbType == NpgsqlDbType.Composite) { throw new InvalidCastException($"When specifying NpgsqlDbType.{nameof(NpgsqlDbType.Enum)}, {nameof(NpgsqlParameter.SpecificType)} must be specified as well"); } // Base, range or array of base/range PostgresType postgresType; if (_postgresTypes.ByNpgsqlDbType.TryGetValue(npgsqlDbType, out postgresType)) { return(postgresType.Activate(this)); } // We don't have a backend type for this NpgsqlDbType. This could be because it's not yet supported by // Npgsql, or that the type is missing in the database (old PG, missing extension...) TypeAndMapping typeAndMapping; if (!HandlerTypesByNpsgqlDbType.TryGetValue(npgsqlDbType, out typeAndMapping)) { throw new NotSupportedException("This NpgsqlDbType isn't supported in Npgsql yet: " + npgsqlDbType); } throw new NpgsqlException($"The PostgreSQL type '{typeAndMapping.Mapping.PgName}', mapped to NpgsqlDbType '{npgsqlDbType}' isn't present in your database. " + "You may need to install an extension or upgrade to a newer version."); } }
#pragma warning disable CA1043 internal TypeHandler this[Type type] #pragma warning restore CA1043 { get { if (ByType.TryGetValue(type, out var handler)) { return(handler); } // Try to find the backend type by a simple lookup on the given CLR type, this will handle base types. if (_postgresTypes.ByClrType.TryGetValue(type, out var postgresType)) { return(postgresType.Activate(this)); } // Try to see if it is an array type var arrayElementType = GetArrayElementType(type); if (arrayElementType != null) { if (ByType.TryGetValue(arrayElementType, out var elementHandler) && elementHandler.PostgresType.NpgsqlDbType.HasValue && ByNpgsqlDbType.TryGetValue(NpgsqlDbType.Array | elementHandler.PostgresType.NpgsqlDbType.Value, out handler)) { return(handler); } // Enum and composite types go through the special _arrayHandlerByType if (ArrayHandlerByType != null && ArrayHandlerByType.TryGetValue(arrayElementType, out handler)) { return(handler); } // Unactivated array // Special check for byte[] - bytea not array of int2 if (type == typeof(byte[])) { if (!_postgresTypes.ByClrType.TryGetValue(typeof(byte[]), out var byteaPostgresType)) { throw new NpgsqlException("The PostgreSQL 'bytea' type is missing"); } return(byteaPostgresType.Activate(this)); } // Get the elements backend type and activate its array backend type if (!_postgresTypes.ByClrType.TryGetValue(arrayElementType, out var elementPostgresType)) { if (arrayElementType.GetTypeInfo().IsEnum) { throw new NotSupportedException($"The CLR enum type {arrayElementType.Name} must be mapped with Npgsql before usage, please refer to the documentation."); } throw new NotSupportedException($"The CLR type {arrayElementType} isn't supported by Npgsql or your PostgreSQL. " + "If you wish to map it to a PostgreSQL composite type you need to register it before usage, please refer to the documentation."); } if (elementPostgresType == null) { throw new NotSupportedException($"The PostgreSQL {arrayElementType.Name} does not have an array type in the database"); } return(elementPostgresType.Array.Activate(this)); } // Range type which hasn't yet been set up if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(NpgsqlRange <>)) { if (!_postgresTypes.ByClrType.TryGetValue(type.GetGenericArguments()[0], out var subtypePostgresType) || subtypePostgresType.Range == null) { throw new NpgsqlException($"The .NET range type {type.Name} isn't supported in your PostgreSQL, use CREATE TYPE AS RANGE"); } return(subtypePostgresType.Range.Activate(this)); } // Nothing worked if (type.GetTypeInfo().IsEnum) { throw new NotSupportedException($"The CLR enum type {type.Name} must be registered with Npgsql before usage, please refer to the documentation."); } if (typeof(IEnumerable).IsAssignableFrom(type)) { throw new NotSupportedException("Npgsql 3.x removed support for writing a parameter with an IEnumerable value, use .ToList()/.ToArray() instead"); } throw new NotSupportedException($"The CLR type {type} isn't supported by Npgsql or your PostgreSQL. " + "If you wish to map it to a PostgreSQL composite type you need to register it before usage, please refer to the documentation."); } }