Сначала интеграция Npgsql с кодом Entity Framework

у меня есть проект, использующий последнюю версию EF CF с PostgreSQL и Npgsql.

моя модель выглядит так:

[Table("mytable")]
public class MyTable
{
    [Column("id")]
    public int Id { get; set; }
    [Column("mycolumn")]
    public string MyColumn { get; set; }
}

и база данных / таблицы / столбцы имеют строчные имена, такие как:

CREATE TABLE mytable
{
    id serial,
    mycolumn character(50)
}

Npgsql генерирует команды SQL с кавычками, поэтому я должен использовать аннотации данных из-за характеристик PostgreSQL, ведьма раздражает. Однако я хотел бы не использовать имена с разделителями цитат в базе данных.

есть ли способ настроить Npgsql, чтобы не включать кавычки при создании команд или принудительных имен таблиц/столбцов в нижнем регистре в сгенерированном SQL?

2 ответов


если я что - то не пропущу-вам нужен какой-то общий способ of changing the naming convention for tables?

EF6 имеет custom conventions feature-это все еще не официальная версия, но если она работает для вас, некоторые ссылки...

http://entityframework.codeplex.com/wikipage?title=Custom%20Conventions

в вашем случае, вам придется провести в классе/Type Я думаю-например (некоторый псевдо-код)...

1) реализовать IConfigurationConvention<Type, EntityTypeConfiguration> (вы можете проверить источник EF для EntityConventionBase)

2) в Apply - изменение способа генерации имен таблиц с помощью конфигурации (ToTable()) - что-то вроде .ToLowerCase()

3) Добавить в соглашения...

например...

public class SmallCapsEntitiesConfigurationConvention
    : IConfigurationConvention<Type, EntityTypeConfiguration>
{
    public void Apply(Type memberInfo, Func<EntityTypeConfiguration> configuration)
    {
        configuration().ToTable(memberInfo.Name.ToLowerInvariant(), null);
    }
}

вы можете увидеть один пример here
http://blog.cincura.net/233167-custom-conventions-in-entity-framework-6-helping-firebird/

в противном случае, я понятия не имею о Npgsql / PostgreSQL-мне это показалось немного "сырым". Но вы можете справиться с этим на стороне EF.


вот пример для EF Core.

преобразование текущего кода tables, properties, keys и indexes в змеиный чехол для Postgre, вы можете использовать его в качестве основы для кастом-конвенций:

using System;
using System.Text.RegularExpressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Npgsql;

namespace Database.Customization
{
    public class PostgreDbContext : DbContext
    {
        private static readonly Regex _keysRegex = new Regex("^(PK|FK|IX)_", RegexOptions.Compiled);

        public PostgreDbContext(DbContextOptions options)
            : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            FixSnakeCaseNames(modelBuilder);
        }

        private void FixSnakeCaseNames(ModelBuilder modelBuilder)
        {
            var mapper = new NpgsqlSnakeCaseNameTranslator();
            foreach (var table in modelBuilder.Model.GetEntityTypes())
            {
                ConvertToSnake(mapper, table);
                foreach (var property in table.GetProperties())
                {
                    ConvertToSnake(mapper, property);
                }

                foreach (var primaryKey in table.GetKeys())
                {
                    ConvertToSnake(mapper, primaryKey);
                }

                foreach (var foreignKey in table.GetForeignKeys())
                {
                    ConvertToSnake(mapper, foreignKey);
                }

                foreach (var indexKey in table.GetIndexes())
                {
                    ConvertToSnake(mapper, indexKey);
                }
            }
        }

        private void ConvertToSnake(INpgsqlNameTranslator mapper, object entity)
        {
            switch (entity)
            {
                case IMutableEntityType table:
                    var relationalTable = table.Relational();
                    relationalTable.TableName = ConvertGeneralToSnake(mapper, relationalTable.TableName);
                    if (relationalTable.TableName.StartsWith("asp_net_"))
                    {
                        relationalTable.TableName = relationalTable.TableName.Replace("asp_net_", string.Empty);
                        relationalTable.Schema = "identity";
                    }

                    break;
                case IMutableProperty property:
                    property.Relational().ColumnName = ConvertGeneralToSnake(mapper, property.Relational().ColumnName);
                    break;
                case IMutableKey primaryKey:
                    primaryKey.Relational().Name = ConvertKeyToSnake(mapper, primaryKey.Relational().Name);
                    break;
                case IMutableForeignKey foreignKey:
                    foreignKey.Relational().Name = ConvertKeyToSnake(mapper, foreignKey.Relational().Name);
                    break;
                case IMutableIndex indexKey:
                    indexKey.Relational().Name = ConvertKeyToSnake(mapper, indexKey.Relational().Name);
                    break;
                default:
                    throw new NotImplementedException("Unexpected type was provided to snake case converter");
            }
        }

        private string ConvertKeyToSnake(INpgsqlNameTranslator mapper, string keyName) =>
            ConvertGeneralToSnake(mapper, _keysRegex.Replace(keyName, match => match.Value.ToLower()));

        private string ConvertGeneralToSnake(INpgsqlNameTranslator mapper, string entityName) =>
            mapper.TranslateMemberName(ModifyNameBeforeConvertion(mapper, entityName));

        protected virtual string ModifyNameBeforeConvertion(INpgsqlNameTranslator mapper, string entityName) => entityName;
    }
}