在 EF Core 2 中使用单数 Table 名称
Using Singular Table Names with EF Core 2
我希望我的域 class 名称与我的数据库 table 名称匹配(无复数形式)。
在 EF Core 1.1 中,我使用以下代码来执行此操作:
public static void RemovePluralisingTableNameConvention(this ModelBuilder modelBuilder)
{
foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
{
entityType.Relational().TableName = entityType.DisplayName();
}
}
在 EF Core 2.0 中,此代码无法编译,因为 Relational()
不是 IMutableEntityType 上的方法。
无论如何,在 EF Core 2.0 中,他们添加了 IPluralizer,记录在此处:
没有太多示例可以说明如何实现与我之前相同的行为。关于如何在 EF Core 2 中删除复数形式的任何线索?
您可以使用完全相同的代码。 Relational()
是extension方法定义在RelationalMetadataExtensions
class里面Microsoft.EntityFrameworkCore.Relational.dll
assembly,所以确保你引用了它。
IPluralizer
呢,正如您从 link 中看到的那样,它只是一个 DbContext 脚手架 的复数挂钩,即实体 class从数据库生成,用于实体类型名称的单数化和 DbSet 名称的复数化。它不用于 table 名称生成。默认的 table 名称约定在文档的 Table Mapping 部分进行了解释:
By convention, each entity will be setup to map to a table with the same name as the DbSet<TEntity>
property that exposes the entity on the derived context. If no DbSet<TEntity>
is included for the given entity, the class name is used.
在 EF Core 2 中,您可以添加一个 hook。令人费解的是,如果您使用它在具有 asp.net 核心应用程序实体的库项目中生成 类,则需要转到程序包管理器控制台 select 您的库项目作为默认项目并在 mvc web 项目中添加这些挂钩。如果您在库中添加钩子,它不会发现钩子。
您可以测试它是否适用于
public void ConfigureDesignTimeServices(IServiceCollection services)
{
throw new Exception("works");
services.AddSingleton<IPluralizer, MyPluralizer>();
}
通过使用 ClrType.Name
,您可以在不使用内部 EF API 调用的情况下这样做
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
// Use the entity name instead of the Context.DbSet<T> name
// refs https://docs.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=fluent-api#table-name
modelBuilder.Entity(entityType.ClrType).ToTable(entityType.ClrType.Name);
}
}
如果有人想在 .NET Core 3.1 中尝试,您可以将扩展方法构建为
public static class ModelBuilderExtension
{
/// <summary>
/// Remove pluralizing table name convention to create table name in singular form.
/// </summary>
public static void RemovePluralizingTableNameConvention(this ModelBuilder modelBuilder)
{
foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
{
entityType.SetTableName(entityType.DisplayName());
}
}
}
确保安装依赖包:Microsoft.EntityFrameworkCore.Relational
这是@Vicram 回答的扩展。
我在 EF Core 5
中应用了它
modelBuilder.Model.GetEntityTypes()
.Configure(e => e.SetTableName(e.DisplayName()));
但是如果您的域中有值对象,它们都将被视为实体类型并在数据库中创建为表。如果您的值对象都继承自 ValueObject
等基类型,您可以使用以下内容:
modelBuilder.Model.GetEntityTypes()
.Where(x => !x.ClrType.IsSubclassOf(typeof(ValueObject)))
.Configure(e => e.SetTableName(e.DisplayName()));
我没有检查其他 EF 核心版本,但肯定是版本 5 中的情况。
EF Core 5 的另一个缺点是,当您在实体模型中使用继承时,设置表名称从 Table-per-Hierarchy (TPH) to Table-per-Type (TPT)
您可以使用以下替代方法(假设您的实体派生自 BaseEntity
class)
modelBuilder.Model.GetEntityTypes()
.Where(x => x.ClrType.BaseType == typeof(BaseEntity))
.Configure(e => e.SetTableName(e.DisplayName()));
其中 Configure
分机是
public static class ModelBuilderExtensions
{
public static void Configure(this IEnumerable<IMutableEntityType> entityTypes, Action<IMutableEntityType> convention)
{
foreach (var entityType in entityTypes)
{
convention(entityType);
}
}
public static void Configure(this IEnumerable<IMutableProperty> propertyTypes, Action<IMutableProperty> convention)
{
foreach (var propertyType in propertyTypes)
{
convention(propertyType);
}
}
}
我希望我的域 class 名称与我的数据库 table 名称匹配(无复数形式)。
在 EF Core 1.1 中,我使用以下代码来执行此操作:
public static void RemovePluralisingTableNameConvention(this ModelBuilder modelBuilder)
{
foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
{
entityType.Relational().TableName = entityType.DisplayName();
}
}
在 EF Core 2.0 中,此代码无法编译,因为 Relational()
不是 IMutableEntityType 上的方法。
无论如何,在 EF Core 2.0 中,他们添加了 IPluralizer,记录在此处:
没有太多示例可以说明如何实现与我之前相同的行为。关于如何在 EF Core 2 中删除复数形式的任何线索?
您可以使用完全相同的代码。 Relational()
是extension方法定义在RelationalMetadataExtensions
class里面Microsoft.EntityFrameworkCore.Relational.dll
assembly,所以确保你引用了它。
IPluralizer
呢,正如您从 link 中看到的那样,它只是一个 DbContext 脚手架 的复数挂钩,即实体 class从数据库生成,用于实体类型名称的单数化和 DbSet 名称的复数化。它不用于 table 名称生成。默认的 table 名称约定在文档的 Table Mapping 部分进行了解释:
By convention, each entity will be setup to map to a table with the same name as the
DbSet<TEntity>
property that exposes the entity on the derived context. If noDbSet<TEntity>
is included for the given entity, the class name is used.
在 EF Core 2 中,您可以添加一个 hook。令人费解的是,如果您使用它在具有 asp.net 核心应用程序实体的库项目中生成 类,则需要转到程序包管理器控制台 select 您的库项目作为默认项目并在 mvc web 项目中添加这些挂钩。如果您在库中添加钩子,它不会发现钩子。
您可以测试它是否适用于
public void ConfigureDesignTimeServices(IServiceCollection services)
{
throw new Exception("works");
services.AddSingleton<IPluralizer, MyPluralizer>();
}
通过使用 ClrType.Name
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
// Use the entity name instead of the Context.DbSet<T> name
// refs https://docs.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=fluent-api#table-name
modelBuilder.Entity(entityType.ClrType).ToTable(entityType.ClrType.Name);
}
}
如果有人想在 .NET Core 3.1 中尝试,您可以将扩展方法构建为
public static class ModelBuilderExtension
{
/// <summary>
/// Remove pluralizing table name convention to create table name in singular form.
/// </summary>
public static void RemovePluralizingTableNameConvention(this ModelBuilder modelBuilder)
{
foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
{
entityType.SetTableName(entityType.DisplayName());
}
}
}
确保安装依赖包:Microsoft.EntityFrameworkCore.Relational
这是@Vicram 回答的扩展。 我在 EF Core 5
中应用了它modelBuilder.Model.GetEntityTypes()
.Configure(e => e.SetTableName(e.DisplayName()));
但是如果您的域中有值对象,它们都将被视为实体类型并在数据库中创建为表。如果您的值对象都继承自 ValueObject
等基类型,您可以使用以下内容:
modelBuilder.Model.GetEntityTypes()
.Where(x => !x.ClrType.IsSubclassOf(typeof(ValueObject)))
.Configure(e => e.SetTableName(e.DisplayName()));
我没有检查其他 EF 核心版本,但肯定是版本 5 中的情况。
EF Core 5 的另一个缺点是,当您在实体模型中使用继承时,设置表名称从 Table-per-Hierarchy (TPH) to Table-per-Type (TPT)
您可以使用以下替代方法(假设您的实体派生自 BaseEntity
class)
modelBuilder.Model.GetEntityTypes()
.Where(x => x.ClrType.BaseType == typeof(BaseEntity))
.Configure(e => e.SetTableName(e.DisplayName()));
其中 Configure
分机是
public static class ModelBuilderExtensions
{
public static void Configure(this IEnumerable<IMutableEntityType> entityTypes, Action<IMutableEntityType> convention)
{
foreach (var entityType in entityTypes)
{
convention(entityType);
}
}
public static void Configure(this IEnumerable<IMutableProperty> propertyTypes, Action<IMutableProperty> convention)
{
foreach (var propertyType in propertyTypes)
{
convention(propertyType);
}
}
}