实体框架7采用代码优先的方法将表名复数化
本文关键字:方法 框架 代码 实体 | 更新日期: 2023-09-27 18:29:35
我是ASP/EF的新手。我在我的个人项目中使用ASP5和实体框架7。
因此,我可以使用代码优先的方法创建数据库和表,但所有表名都是单数,默认情况下不使用复数。
在我的ServerMatrixDemoDB DbContext文件中,我创建了以下数据库集:
public class ServerMatrixDemoDB : DbContext
{
public ServerMatrixDemoDB()
{
Database.EnsureCreated();
}
public DbSet<Domain> Domains { get; set; }
public DbSet<Environment> Environments { get; set; }
public DbSet<Network> Networks { get; set; }
public DbSet<OsVersion> OsVersions { get; set; }
public DbSet<Tier> Tiers { get; set; }
public DbSet<Service> Services { get; set; }
public DbSet<HardwareType> HardwareTypes { get; set; }
public DbSet<Powershell> Powershell { get; set; }
public DbSet<DotNetVersion> DotNetVersions { get; set; }
public DbSet<Status> Status { get; set; }
public DbSet<Servers> Servers { get; set; }
public DbSet<Application> Applications { get; set; }
}
在我的startup.cs文件中,我使用以下代码:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc() // Add MVC Dependency.
.AddJsonOptions(
opt =>
{
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // Api convert all property names to CamelCase.
}
);
services.AddLogging(); // Enable Logging for database errors.
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<ServerMatrixDemoDB>(options =>
{
options.UseSqlServer(@"Server=.'SQLEXPRESS;user id=sa;password='passwrd';Database=ServerMatrixDemoDB;integrated security=True;");
});
services.AddTransient<ServerMatrixDemoSeedData>();
}
一旦我构建并运行了项目,就会创建一个数据库和表,但所有的表名都是单数。有没有一种方法可以用代码优先的方法将表名复数化?
您可以在OnModelCreating重载中执行此操作,如-
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
modelBuilder.Entity(entity.Name).ToTable(entity.Name + "s");
}
}
你也可以使用"数据注释"
[Table("blogs")]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
或Fluent Api
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.ToTable("blogs");
}
}
有关更多详细信息,请参阅-EF7 文档
当前代码将tables
、properties
、keys
和indexes
转换为Postgre
的snake case,您可以将其用作自定义约定的基础:
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;
}
}
还可以使用PluralizationService并创建从TableAttribute:继承的属性
/// <summary>
/// Specifies the database table that a class is mapped to with pluralization.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "We want users to be able to extend this class")]
public class PluralizedTableAttribute : TableAttribute
{
private const string _englishCultureName = "en-us";
/// <summary>
/// Initializes a new instance of the <see cref="PluralizedTableAttribute"/> class.
/// </summary>
/// <param name="name">The table name.</param>
public PluralizedTableAttribute(string name)
:base(PluralizationService.CreateService(CultureInfo.GetCultureInfo(_englishCultureName)).Pluralize(name)) // pluralization only suported in English.
{
}
}
你会像使用AtbleAttribute一样使用它,只是现在所有的东西都会被引诱
private const string _englishCultureName = "en-us";
public string GetPuralTableName(string singularTableName)
{
// pluralization only suported in English.
return PluralizationService.CreateService(CultureInfo.GetCultureInfo(_englishCultureName)).Pluralize(singularTableName);
}