如何使用 Oracle 和 SQL Server 在 .NET 4.5 C# Entity Framework 6 中将列映射为大写?

How do I map a column to uppercase in .NET 4.5 C# Entity Framework 6 using both Oracle and SQL Server?

我在我的项目中使用 C#、.NET 4.5 和 Entity Framework 6。它同时使用 Oracle 和 SQL 服务器,具体取决于客户端的安装。

该方法是数据库优先的,因为在我们决定将 ORM 从 NHibernate 更改为 Entity Framework 6.

时该数据库已经存在

映射如下所示:

ToTable(schema + ".Motorista");
Property(x => x.Criacao).HasColumnName("criacao").IsOptional();

table 和列名在映射中都是 PascalCase,这在 SQL Server 上工作正常,但在 Oracle 中,所有名称都是大写,这会导致错误:

ORA-00942: table or view does not exist

如果我手动将其设为大写,那么它在 Oracle 上工作正常。但由于与 SQL 服务器的兼容性,我不能这样做。

如何在使用 Oracle 时 Entity Framework 将所有名称大写?

我可以在这种情况下使用约定吗?

检查命名连接字符串中的 providerName 属性以查看您的连接是针对 SQL Server 还是 Oracle(或者在配置的 appSettings 部分添加冗余值)。然后按照@AaronLS 的建议进行操作,并添加一个辅助方法来正确区分您的姓名并应用任何其他格式。 helper 方法的任务是如上所述检查数据库类型并应用或不应用 casing/formatting.

这是一个例子。

public class MyDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new SomeMappedTypeMapper());
        base.OnModelCreating(modelBuilder);
    }
}

public class SomeMappedType
{
    public int SomeMappedColumnId { get; set; }
    public string SomeMappedColumn { get; set; }
}

public class SomeMappedTypeMapper : EntityTypeConfiguration<SomeMappedType>
{
    public SomeMappedTypeMapper()
    {
        this.HasKey(x => x.SomeMappedColumnId);
        this.ToTable("SomeMappedType"); // If needed, apply the same technique as used in the column name extension

        this.Property(x => x.SomeMappedColumnId).HasColumnNameV2("SomeMappedColumnId").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(x => x.SomeMappedColumn).HasColumnNameV2("SomeMappedColumn");
    }
}

public static class TypeHelper
{
    private static bool isOracle;
    static TypeHelper()
    {
        isOracle = System.Configuration.ConfigurationManager.ConnectionStrings["yourDbConnectionName"].ProviderName.IndexOf("oracle", StringComparison.OrdinalIgnoreCase) >= 0;
    }
    public static PrimitivePropertyConfiguration HasColumnNameV2(this PrimitivePropertyConfiguration property, string columnName)
    {
        if (isOracle)
            return property.HasColumnName(columnName.ToUpper());
        return property.HasColumnName(columnName);
    }
}

当数据库名称(tables和列)等于class和属性模型中的class名称时,很容易引入自定义代码优先约定:

在上下文的 OnModelCreating 重载中,您可以添加这些行以添加约定 table 和列名称分别从 class 和 属性 名称派生的方式:

modelBuilder.Types().Configure
    (c => c.ToTable(c.ClrType.Name.ToUpper(), schema));

modelBuilder.Properties().Configure
    (c => c.HasColumnName(c.ClrPropertyInfo.Name.ToUpper()));

当然,您应该有条件地执行此操作,即在连接到 Oracle 时。例如,通过检查 OnOracle 之类的全局常量,您可以通过

进行设置
ConfigurationManager.ConnectionStrings[0].ProviderName
    == "System.Data.OracleClient"

应用程序启动时。

考虑一个名为 "Person" 的 table 在 SQL 服务器中有一个名为 "Name" 的列,但在 oracle 中 table 被称为 "PERSON"有一个名为 "NAME".

的列

通过将以下代码添加到 DBContext 类的 OnModelCreating

,我们能够在 oracle 数据库上使用针对 sql 服务器生成的模型
modelBuilder.Entity<Person>()
  .HasEntitySetName("Person")
  .ToTable("PERSON");

modelBuilder.Entity<Person>()
  .Property(t => t.Name)
  .HasColumnName("NAME");

这个 link 在 EF CORE 中,但它可能对你有帮助,它转换为 ToUpper,但你可以更改为 ToLower,你也可以使用 Nuget ** Humanizer ** 进行另一种大写。

将该文件导入您的项目并像这样使用它。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.ToUpperCaseTables();
    modelBuilder.ToUpperCaseColumns();
    // ...
}