Сначала интеграция 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;
}
}