61

有没有办法完成这段代码在 EF Core RC 2 中所做的事情?

protected override void OnModelCreating(ModelBuilder modelBuilder)
{    
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
4

8 回答 8

125

从 EF RC2 版本开始,没有这方面的约定。这来自 EF Core 团队:

在过去的 EF Core 预发行版中,实体的表名称与实体类名称相同。在 RC2 中,我们现在使用 DbSet 属性的名称。如果没有为给定的实体类型定义 DbSet 属性,则使用实体类名称。


现在,如果您想恢复为表的 RC1 命名约定,您有 3 种方法可以使用:


1. 为 DbSet 属性选择单数名称:

一种方法是单数化您的 DbSet 属性名称(我不喜欢)。例如,假设您有一个Book实体,并且您想映射到Book表:

public DbSet<Book> Book { get; set; }


2. 使用 ToTable() Fluent API:

您当然可以始终使用 fluent API 来覆盖任何约定,并将表名指定为您想要的任何内容:

modelBuilder.Entity<Book>().ToTable("Book");


3. 编写自定义约定:

仅仅因为 EF Core RC2 对此没有约定,并不意味着我们不能自己编写。为此,首先我们需要在ModelBuilder对象上创建一个扩展方法:

using Microsoft.EntityFrameworkCore.Metadata.Internal;

public static class ModelBuilderExtensions 
{
    public static void RemovePluralizingTableNameConvention(this ModelBuilder modelBuilder)
    {
        foreach (IMutableEntityType entity in modelBuilder.Model.GetEntityTypes())
        {
            entity.Relational().TableName = entity.DisplayName();
        }
    }
}

然后我们只需从DbContext对象的OnModelCreating方法中调用它:

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


收盘时:

我不喜欢复数表名,并且我比其他选项更喜欢最后一个选项,并同意了。也就是说,这是我个人的意见,其他开发人员可能会发现这 3 种方式中的任何一种都比其他方式更有利,并选择采用 :)

于 2016-05-28T19:20:36.240 回答
60

对于 EF Core 3.0 及更高版本,使用它来设置TableName属性(因为entity.Relational()不再存在):

public static class ModelBuilderExtensions 
{
    public static void RemovePluralizingTableNameConvention(this ModelBuilder modelBuilder)
    {
        foreach (IMutableEntityType entity in modelBuilder.Model.GetEntityTypes())
        {
            entity.SetTableName(entity.DisplayName());
        }
    }
}
于 2019-08-27T08:15:55.697 回答
10

EF Core 版本似乎不支持entity.DisplayName. 这是一个可行的选择:

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
    // Skip shadow types
    if (entityType.ClrType == null)
        continue;

    entityType.Relational().TableName = entityType.ClrType.Name;
}
于 2016-08-14T15:06:27.367 回答
7

这也是一种选择:

 using System.ComponentModel.DataAnnotations.Schema;

 [Table("Book")]
 public class Book
 {...}

尽管您需要在每个实体上对其进行注释

于 2019-04-26T19:24:16.840 回答
5

在 Entity Framework NET core v2 中,您可以选择复数或单数DbSetsCollections带有钩子。

public class MyDesignTimeServices : IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection services)
    {
        services.AddSingleton<IPluralizer, MyPluralizer>();
    }
}

public class MyPluralizer : IPluralizer
{
    public string Pluralize(string name)
    {
        return Inflector.Inflector.Pluralize(name) ?? name;
    }

    public string Singularize(string name)
    {
        return Inflector.Inflector.Singularize(name) ?? name;
    }
}

有关更多信息,请参阅此答案:https ://stackoverflow.com/a/47410837/869033

于 2017-11-21T10:32:13.350 回答
4

EF Core 5 在更新 Db 上下文时使用开关“-NoPluralize”解决了问题:

Scaffold-DbContext "..conn str.." Microsoft.EntityFrameworkCore.SqlServer -OutputDir EntityDbContext -Project DoctorsExpress.Domain -Force -NoPluralize
于 2021-01-29T10:41:47.063 回答
0

我将它用于 EF Core 3.1 以保留[Table("some_table_name")]实体类型的注释,尽管ConventionAnnotation它是一个内部类。

static class UseEntityTypeNameForTableNameExtension
{
    public static void UseEntityTypeNameForTableName(this ModelBuilder modelBuilder)
    {
        foreach (var entity in modelBuilder.Model.GetEntityTypes())
        {
            var tableNameAnnotation = (ConventionAnnotation)entity.FindAnnotation(RelationalAnnotationNames.TableName);
#pragma warning disable EF1001
            var configurationSource = tableNameAnnotation.GetConfigurationSource();
#pragma warning restore EF1001
            if (configurationSource != ConfigurationSource.Convention)
            {
                // Set explicitly using Fluent API or has TableAttribute DataAnnotation
                continue;
            }
            var defaultTableName = entity.GetDefaultTableName();
            entity.SetTableName(defaultTableName);
        }
    }
}
于 2020-05-07T10:38:51.987 回答
-2

我去添加一个虚拟

public virtual DbSet<TableName> TableName{ get; set; }
public DbSet<TableName> TableNames { get; set; }

TableNames.FirstOrDefault();
于 2020-07-08T23:16:03.847 回答