Entity Framework Core RC2 表名复数

Posted

技术标签:

【中文标题】Entity Framework Core RC2 表名复数【英文标题】:Entity Framework Core RC2 table name pluralization 【发布时间】:2016-09-26 08:39:52 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

在 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 种方式中的任何一种都比其他方式更有利,并选择采用它:)

【讨论】:

谢谢莫特萨。我认为现在我只需在实体上设置表名。 @Tančev Saša 我试图在base.OnModelCreating(builder); 之前调用modelBuilder.RemovePluralizingTableNameConvention(); 并且身份表的名称正常 IMutableEntityType 没有 Relational() 方法,是不是改了? entity.Relational().TableName = entity.DisplayName();不适用于 .net core 3 你应该可以使用 entity.SetTableName(entity.DisplayName());【参考方案2】:

对于 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());
        
    

【讨论】:

如果您将此方法用于继承的实体,您将收到错误...Only base type entity types can be mapped to a table.。为了解决这个问题,我使用了条件if (entity.BaseType == null)。基类将返回null,而继承的类显然会返回基类型。 @Métoule : 调用 modelBuilder.RemovePluralizingTableNameConvention()entity.ToView("MyView") 结合使用时会出现问题:实体随后被标记为表格而不是视图。 @Métoule 请检查 EF Core 5 的可能问题和解决方法***.com/a/65585664/1769622 .NET 6 怎么样? .NET 6 中既不存在 entity.Relational() 也不存在 entity.SetTableName()。 @Creative: entity.SetTableName 存在于 EF Core 6 中。【参考方案3】:

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;

【讨论】:

entity.DisplayNameMicrosoft.EntityFrameworkCore.Metadata.Internal 命名空间(实际上是公共的,而不是internal)中的扩展方法。【参考方案4】:

这也是一种选择:

 using System.ComponentModel.DataAnnotations.Schema;

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

虽然您需要在每个实体上对其进行注释

【讨论】:

我发现自己想通过模式进行组织,所以无论如何我在每个类上都使用这个标签进行注释。举个例子:[Table("Book", Schema = "library")]【参考方案5】:

在 Entity Framework NET core v2 中,您可以选择 pluralize 或使用钩子将 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://***.com/a/47410837/869033

【讨论】:

【参考方案6】:

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

Scaffold-DbContext "..conn str.." Microsoft.EntityFrameworkCore.SqlServer -OutputDir EntityDbContext -Project DoctorsExpress.Domain -Force -NoPluralize

【讨论】:

应该是--no-pluralize【参考方案7】:

我在 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);
        
    

【讨论】:

【参考方案8】:

我添加了一个虚拟

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

TableNames.FirstOrDefault();

【讨论】:

以上是关于Entity Framework Core RC2 表名复数的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core 6.0 预览4 性能改进

Entity Framework Core快速开始

Entity Framework Core 快速开始

EF6 System.Data.Entity.Core.EntityKey 在 Entity Framework Core 中的等价物是啥?

张高兴的 Entity Framework Core 即学即用:创建第一个 EF Core 应用

Entity Framework Core 迁移命令