public static void FixSnakeCaseNames(ModelBuilder modelBuilder) { foreach (var entity in modelBuilder.Model.GetEntityTypes()) { // modify column names foreach (var property in entity.GetProperties()) { property.Relational().ColumnName = NameTranslator.TranslateMemberName(property.Relational().ColumnName); } // modify table name entity.Relational().TableName = NameTranslator.TranslateMemberName(entity.Relational().TableName); } }
static void GenerateMappings(INpgsqlNameTranslator nameTranslator, Dictionary <TEnum, string> enumToLabel, Dictionary <string, TEnum> labelToEnum) { foreach (var field in typeof(TEnum).GetFields(BindingFlags.Static | BindingFlags.Public)) { var attribute = (PgNameAttribute)field.GetCustomAttributes(typeof(PgNameAttribute), false).FirstOrDefault(); var enumName = attribute == null ? nameTranslator.TranslateMemberName(field.Name) : attribute.PgName; var enumValue = (Enum)field.GetValue(null); enumToLabel[(TEnum)(object)enumValue] = enumName; labelToEnum[enumName] = (TEnum)(object)enumValue; } }
internal EnumTypeHandlerFactory(INpgsqlNameTranslator nameTranslator) { foreach (var field in typeof(TEnum).GetFields(BindingFlags.Static | BindingFlags.Public)) { var attribute = (PgNameAttribute)field.GetCustomAttributes(typeof(PgNameAttribute), false).FirstOrDefault(); var enumName = attribute == null ? nameTranslator.TranslateMemberName(field.Name) : attribute.PgName; var enumValue = (Enum)field.GetValue(null); _enumToLabel[(TEnum)(object)enumValue] = enumName; _labelToEnum[enumName] = (TEnum)(object)enumValue; } }
void Map(Type type) { Debug.Assert(_resolvedType != type); _enumToLabel.Clear(); _labelToEnum.Clear(); foreach (var field in type.GetFields(BindingFlags.Static | BindingFlags.Public)) { var attribute = (PgNameAttribute)field.GetCustomAttributes(typeof(PgNameAttribute), false).FirstOrDefault(); var enumName = attribute == null ? _nameTranslator.TranslateMemberName(field.Name) : attribute.PgName; var enumValue = (Enum)field.GetValue(null); _enumToLabel[enumValue] = enumName; _labelToEnum[enumName] = enumValue; } _resolvedType = type; }
private string ConvertGeneralToSnake(INpgsqlNameTranslator mapper, string entityName) => mapper.TranslateMemberName(ModifyNameBeforeConvertion(mapper, entityName));
static CompositeMemberHandler <T>[] CreateMemberHandlers(PostgresCompositeType pgType, ConnectorTypeMapper typeMapper, INpgsqlNameTranslator nameTranslator) { var pgFields = pgType.Fields; var clrType = typeof(T); var clrMemberHandlers = new CompositeMemberHandler <T> [pgFields.Count]; var clrMemberHandlerCount = 0; var clrMemberHandlerType = IsValueType <T> .Value ? typeof(CompositeStructMemberHandler <,>) : typeof(CompositeClassMemberHandler <,>); foreach (var clrProperty in clrType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { CreateMemberHandler(clrProperty, clrProperty.PropertyType); } foreach (var clrField in clrType.GetFields(BindingFlags.Instance | BindingFlags.Public)) { CreateMemberHandler(clrField, clrField.FieldType); } if (clrMemberHandlerCount != pgFields.Count) { var notMappedFields = string.Join(", ", clrMemberHandlers .Select((member, memberIndex) => member == null ? $"'{pgFields[memberIndex].Name}'" : null) .Where(member => member != null)); throw new InvalidOperationException($"PostgreSQL composite type {pgType.DisplayName} contains fields {notMappedFields} which could not match any on CLR type {clrType.Name}"); } return(clrMemberHandlers); void CreateMemberHandler(MemberInfo clrMember, Type clrMemberType) { var attr = clrMember.GetCustomAttribute <PgNameAttribute>(); var name = attr?.PgName ?? nameTranslator.TranslateMemberName(clrMember.Name); for (var pgFieldIndex = pgFields.Count - 1; pgFieldIndex >= 0; --pgFieldIndex) { var pgField = pgFields[pgFieldIndex]; if (pgField.Name != name) { continue; } if (clrMemberHandlers[pgFieldIndex] != null) { throw new AmbiguousMatchException($"Multiple class members are mapped to the '{pgField.Name}' field."); } if (!typeMapper.TryGetByOID(pgField.Type.OID, out var handler)) { throw new NpgsqlException($"PostgreSQL composite type {pgType.DisplayName} has field {pgField.Type.DisplayName} with an unknown type (OID = {pgField.Type.OID})."); } clrMemberHandlerCount++; clrMemberHandlers[pgFieldIndex] = (CompositeMemberHandler <T>)Activator.CreateInstance( clrMemberHandlerType.MakeGenericType(clrType, clrMemberType), BindingFlags.Instance | BindingFlags.Public, binder: null, args: new object[] { clrMember, pgField.Type, handler }, culture: null) !; break; } } }
static CompositeConstructorHandler <T>?CreateConstructorHandler(PostgresCompositeType pgType, ConnectorTypeMapper typeMapper, INpgsqlNameTranslator nameTranslator) { var pgFields = pgType.Fields; var clrType = typeof(T); ConstructorInfo?clrDefaultConstructor = null; foreach (var clrConstructor in clrType.GetConstructors()) { var clrParameters = clrConstructor.GetParameters(); if (clrParameters.Length != pgFields.Count) { if (clrParameters.Length == 0) { clrDefaultConstructor = clrConstructor; } continue; } var clrParameterHandlerCount = 0; var clrParametersMapped = new ParameterInfo[pgFields.Count]; foreach (var clrParameter in clrParameters) { var attr = clrParameter.GetCustomAttribute <PgNameAttribute>(); var name = attr?.PgName ?? (clrParameter.Name is string clrName ? nameTranslator.TranslateMemberName(clrName) : null); if (name is null) { break; } for (var pgFieldIndex = pgFields.Count - 1; pgFieldIndex >= 0; --pgFieldIndex) { var pgField = pgFields[pgFieldIndex]; if (pgField.Name != name) { continue; } if (clrParametersMapped[pgFieldIndex] != null) { throw new AmbiguousMatchException($"Multiple constructor parameters are mapped to the '{pgField.Name}' field."); } clrParameterHandlerCount++; clrParametersMapped[pgFieldIndex] = clrParameter; break; } } if (clrParameterHandlerCount < pgFields.Count) { continue; } var clrParameterHandlers = new CompositeParameterHandler[pgFields.Count]; for (var pgFieldIndex = 0; pgFieldIndex < pgFields.Count; ++pgFieldIndex) { var pgField = pgFields[pgFieldIndex]; if (!typeMapper.TryGetByOID(pgField.Type.OID, out var handler)) { throw new NpgsqlException($"PostgreSQL composite type {pgType.DisplayName} has field {pgField.Type.DisplayName} with an unknown type (OID = {pgField.Type.OID})."); } var clrParameter = clrParametersMapped[pgFieldIndex]; var clrParameterHandlerType = typeof(CompositeParameterHandler <>) .MakeGenericType(clrParameter.ParameterType); clrParameterHandlers[pgFieldIndex] = (CompositeParameterHandler)Activator.CreateInstance( clrParameterHandlerType, BindingFlags.Instance | BindingFlags.Public, binder: null, args: new object[] { handler, clrParameter }, culture: null) !; } return(CompositeConstructorHandler <T> .Create(pgType, clrConstructor, clrParameterHandlers)); } if (clrDefaultConstructor is null && !clrType.IsValueType) { throw new InvalidOperationException($"No parameterless constructor defined for type '{clrType}'."); } return(null); }
// See: https://github.com/npgsql/npgsql/blob/dev/src/Npgsql/TypeHandlers/EnumHandler.cs#L118-L129 private static string[] GetMemberPgNames <TEnum>(INpgsqlNameTranslator nameTranslator) where TEnum : struct, Enum => typeof(TEnum) .GetFields(BindingFlags.Static | BindingFlags.Public) .Select(x => x.GetCustomAttribute <PgNameAttribute>()?.PgName ?? nameTranslator.TranslateMemberName(x.Name)) .ToArray();
static string ConvertGeneralToSnake(INpgsqlNameTranslator mapper, string entityName) => mapper.TranslateMemberName(entityName);
static Dictionary <object, string> CreateValueMapping([NotNull] Type enumType, [NotNull] INpgsqlNameTranslator nameTranslator) => enumType.GetFields(BindingFlags.Static | BindingFlags.Public) .ToDictionary( x => x.GetValue(null), x => x.GetCustomAttribute <PgNameAttribute>()?.PgName ?? nameTranslator.TranslateMemberName(x.Name));
protected override string GenerateNonNullSqlLiteral(object value) => $"'{_nameTranslator.TranslateMemberName(value.ToString())}'::{StoreType}";
private void MapColumnNames(IMutableProperty property) { var columnName = property.Relational().ColumnName; property.Relational().ColumnName = _nameTranslator.TranslateMemberName(columnName); }
protected override string GenerateNonNullSqlLiteral(object value) => $"'{_nameTranslator.TranslateMemberName(value.ToString())}'::{_sqlGenerationHelper.DelimitIdentifier(StoreType)}";