引用标识符 - EF代码优先

时间:2017-09-19 21:42:11

标签: c# sql-server oracle entity-framework oracle11g

在EF 6中是否有任何选项可以在Oracle中创建带有非加引号标识符的表?

背景

我们一直在使用EF代码。直到现在产品应该支持SQL Server,现在Oracle由PO添加。对于大多数功能,我们使用带有LINQ的EF模型来填充数据,但是由于很少有特殊功能,我们编写了生成sql查询的引擎。

示例: 从Tab1中选择Col1,Col2,Col3

因此,上面生成的查询与SQL Server数据库一起工作正常,因为EF在SQL Server中生成了带有非引号标识符的表。

但同样的查询在Oracle中不起作用,因为EF生成了带引号标识符的所有表。因此,要成功执行上述查询,引擎必须生成:

选择" Col1"," Col2"," Col3"来自" Tab1"

我想避免更改查询引擎。

那么,EF 6中是否有任何选项可以在Oracle中创建带有非加引号标识符的表?

非常感谢......

1 个答案:

答案 0 :(得分:2)

这里的诀窍是,您不需要取消引用的标识符,只需将所有标识符强制为全部大写。在Oracle中,未引用的标识符将转换为目录中的所有大写字母。然后,在解析SQL时,Oracle会将SQL中的非引用标识符转换为所有大写字母以匹配目录中的标识符。

这就是Oracle如何创建非案例敏感目录的错觉。

您可以使用Attributes,Fluent API或自定义约定强制您的实体和属性映射到all-caps数据库标识符。

这里有一个关于如何使用自定义约定来规范化Oracle表和列标识符为全部带下划线的概念(假设它们的实体属性和CLR类型名称是PascalCase)。

namespace OracleConventions
{
    using System.Data.Entity.Core.Metadata.Edm;
    using System.Data.Entity.Infrastructure;
    using System.Data.Entity.Infrastructure.Pluralization;
    using System.Data.Entity.ModelConfiguration.Conventions;
    using System.Text.RegularExpressions;

    static class Identifiers
    {
        public static string CreateIdentifier(string entityName)
        {
            var result = Regex.Replace(entityName, "[a-z][A-Z]", m => m.Value[0] + "_" + m.Value[1]);

            return result.ToUpper();
        }
    }

    public class AllCapsTableAndColumnConvention : System.Data.Entity.ModelConfiguration.Conventions.Convention
    {

        public AllCapsTableAndColumnConvention()
        {
            var ps = (IPluralizationService)DbConfiguration.DependencyResolver.GetService(typeof(IPluralizationService), null);

            this.Types().Configure(t => t.ToTable(Identifiers.CreateIdentifier(ps.Pluralize(t.ClrType.Name))));
            this.Properties().Configure(p => p.HasColumnName(Identifiers.CreateIdentifier(p.ClrPropertyInfo.Name)));           

        }
    }
    public class AllCapsForeignKeyConvention : IStoreModelConvention<AssociationType>
    {

        public void Apply(AssociationType association, DbModel model)
        {
            // Identify ForeignKey properties (including IAs)  
            if (association.IsForeignKey)
            {
                // rename FK columns  
                var constraint = association.Constraint;
                foreach (var p in constraint.FromProperties.Union(constraint.ToProperties))
                {
                    p.Name = Identifiers.CreateIdentifier(p.Name);
                }

            }
        }

    }

}

然后,您将在OnModelCreating

中注册约定
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Add(new OracleConventions.AllCapsTableAndColumnConvention());
    modelBuilder.Conventions.Add(new OracleConventions.AllCapsForeignKeyConvention());
    base.OnModelCreating(modelBuilder);
}