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

Posted

技术标签:

【中文标题】如何使用 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? 【发布时间】:2015-04-09 17:01:10 【问题描述】:

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

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

映射如下所示:

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

映射中的表名和列名都使用 PascalCase,这在 SQL Server 上运行良好,但在 Oracle 中,所有名称都是大写,这会导致错误:

ORA-00942: 表或视图不存在

如果我手动将其设为大写,那么它在 Oracle 上运行良好。但由于与 SQL Server 的兼容性,我不能这样做。

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

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

【问题讨论】:

您从 NHibernate 转到了 EF? ***.com/questions/17185921/… 一种解决方法是使用配置值并在您的流利映射中有条件地检查它,如果已设置,则将名称转换为大写。因此,您的客户端将修改此配置值以指定 Oracle,您的代码将检查该设置。您可以使用流畅的样式帮助方法.ToAppropriateName 或类似的方法,使其更易于重用。当然,让客户端修改配置文件可能会很痛苦,具体取决于您拥有多少客户端。 IDK 如果有更简单的方法可以在运行时以编程方式检查连接字符串是否指向 Oracle。 检查命名连接字符串中的 providerName 属性以查看您的连接是针对 Sql Server 还是 Oracle(或者在配置的 appSettings 部分添加冗余值)。然后按照@AaronLS 的建议进行操作,并添加一个帮助方法来正确区分您的姓名并应用任何其他格式。辅助方法的任务应该是检查上面提到的数据库类型并应用或不应用大小写/格式。 表名和列名是否总是与类名和属性名相同(大小写除外)?如果是这样,您可以使用自定义代码优先约定。 @GertArnold 是的,除了大小写之外,它们都是相同的。如何使用自定义约定来实现这一点(我使用的是数据库优先方法)?我研究并发现只有 ef 4 和 5 的示例(我使用的是 6 并且更改了一些类名)。谁能帮忙举个例子?谢谢 【参考方案1】:

当数据库名称(表和列)与类模型中的类和属性名称相同时,很容易引入自定义代码优先约定

在上下文的OnModelCreating 重载中,您可以添加这些行来添加约定,分别从类名和属性名派生表名和列名:

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"

在应用程序启动时。

【讨论】:

我试过了,但没有触发。我检查了生成的 SQL 并保持不变。 您是否这样做而不是当前的 ToTable 语句? 不。我保留了映射并添加了这个。将尝试删除“ToTable”映射并仅保留此配置。 个人ToTable 映射推翻了约定,所以这就是原因。 这应该是公认的答案,简单而强大。效果很好,谢谢! - 没有使用第二个代码块,因为所有实体都来自 oracle【参考方案2】:

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

这是一个例子。

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

【讨论】:

感谢@Igor,Helper 扩展解决了这个问题。【参考方案3】:

考虑一个名为“Person”的表,在 SQL Server 中包含一个名为“Name”的列,但在 oracle 中,该表名为“PERSON”,其中包含一个名为“NAME”的列。

通过将以下代码添加到 DBContext 类的 OnModelCreating 中,我们能够在我们的 oracle 数据库上使用针对 sql server 生成的模型

modelBuilder.Entity<Person>()
  .HasEntitySetName("Person")
  .ToTable("PERSON");

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

【讨论】:

【参考方案4】:

link 在 EF CORE 中,但它可能对您有所帮助,这将转换 ToUpper,但您可以更改 ToLower,您还可以使用 Nuget ** Humanizer ** 进行另一种类型的大写。

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

protected override void OnModelCreating(ModelBuilder modelBuilder)

    base.OnModelCreating(modelBuilder);
    modelBuilder.ToUpperCaseTables();
    modelBuilder.ToUpperCaseColumns();
    // ...

【讨论】:

以上是关于如何使用 Oracle 和 SQL Server 将 .NET 4.5 C# Entity Framework 6 中的列映射为大写?的主要内容,如果未能解决你的问题,请参考以下文章

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

如何将 MS-SQL Server SELECT 查询转换/迁移到 Oracle 和 MySQL?

Oracle, SQL Server, My SQL如何实现数据分页查询语句

sql server与oracle链接问题

SQL SERVER2012同步Oracle数据

Oracle和sql server中复制表结构和表数据的sql语句