在EF Core 2

时间:2017-09-29 22:32:26

标签: c# ef-code-first entity-framework-core

我希望我的域类名与我的db表名匹配(无复数)。

在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,记录在这里:

https://github.com/aspnet/EntityFramework.Docs/blob/master/entity-framework/core/what-is-new/index.md#pluralization-hook-for-dbcontext-scaffolding

没有很多例子可以展示如何实现我以前的相同行为。有关如何在EF Core 2中删除多重化的任何线索?

5 个答案:

答案 0 :(得分:7)

如果有人想在.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

答案 1 :(得分:4)

您可以使用完全相同的代码。 Relational()Microsoft.EntityFrameworkCore.Relational.dll 程序集RelationalMetadataExtensions类中定义的扩展名方法,因此请确保您引用它。

IPluralizer开始,你可以从链接看到它只是一个用于DbContext Scaffolding 的 Pluralization钩子,即从数据库生成实体类,用于单一化实体类型名称和复数DbSet名称。它不用于表名生成。默认表名约定在文档的Table Mapping部分中进行了解释:

  

按照惯例,每个实体都将设置为映射到与DbSet<TEntity>属性同名的表,该属性在派生上下文中公开实体。如果给定实体不包含DbSet<TEntity>,则使用类名。

答案 2 :(得分:3)

这是@Vicram'a 答案的扩展。 我在 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) 更改为 Table-per-Type (TPT)

您可以使用以下替代方法(假设您的实体派生自 BaseEntity 类)

modelBuilder.Model.GetEntityTypes()
    .Where(x => x.ClrType.BaseType == typeof(BaseEntity))
    .Configure(e => e.SetTableName(e.DisplayName()));

答案 3 :(得分:1)

您可以通过使用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/relational/tables#conventions
        modelBuilder.Entity(entityType.ClrType).ToTable(entityType.ClrType.Name);
    }
}

答案 4 :(得分:0)

在EF Core 2中,您可以添加hook。什么是思维弯曲是如果你使用它来生成具有asp.net核心应用程序实体的库项目中的类,你需要去包管理器控制台选择你的库项目作为默认项目并添加这些钩子在mvc web项目。如果你在库中添加一个钩子,它就不会发现钩子。

您可以使用

进行测试
public void ConfigureDesignTimeServices(IServiceCollection services)
{
    throw new Exception("works");
    services.AddSingleton<IPluralizer, MyPluralizer>();
}