Oracle与EntityFramework(EF)的一些事情

概要

Oracle 和EF 一起用的时候总会有各种问题,这里总结一下解决办法。

模式 Schema

用过Oracle的人应该知道,其实Oracle的用户名一般就是它的模式名称,如果你在用database first 模式构建edmx文件,那么恭喜你,一旦你换了用户名就会出错!

所以尽量避免用edmx来配合使用,推荐用model first模式,就是改了数据结构,自己把对应的模型也改了。

在这个时候,还是避免不了模式问题,这里提供一个办法:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    //模式调整
    modelBuilder.HasDefaultSchema(GetSchemaByConName(ConnectionName));
}

这样就根据数据库连接字符串来初始化模式,避免被模式坑了。

表和列名大写

Oracle 的表名和列名默认都是大写的,区分大小写,当初遇到的时候可是把我坑的好惨。。。

后面找到方法将 所有列名(属性名),表名全部转换为大写,添加统一的映射。

        /// <summary>
        /// create
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //表名调整
            modelBuilder.Types().Configure(x => x.ToTable(EFStartup.SetTableName(x.ClrType.Name)));

            if (IsOracleDb)
            {
                //模式调整
                modelBuilder.HasDefaultSchema(EFStartup.GetSchemaByConName(ConnectionName));
                //列名调整
                modelBuilder.Properties().Configure(c => c.HasColumnName(c.ClrPropertyInfo.Name.ToUpper()));
            }
        }

    /// <summary>
    /// EF预热
    /// </summary>
    internal static class EFStartup
    {
        /// <summary>
        /// 通过数据库连接名称获取模式名称(Oracle用)
        /// </summary>
        /// <param name="conName"></param>
        /// <returns></returns>
        internal static string GetSchemaByConName(string conName)
        {
            if (string.IsNullOrEmpty(conName)) throw new ArgumentNullException(nameof(conName));
            var c = ConfigurationManager.ConnectionStrings[conName];
            if (c == null)
                throw new InvalidOperationException("Db Connection Not Found :" + conName);
            if (string.IsNullOrEmpty(c.ConnectionString))
                throw new Exception($"ConnectionString {conName} is empty!");
            //获取User Id
            var sp = c.ConnectionString.Split(';');
            var u = sp.Where(x => !string.IsNullOrEmpty(x) && x.Contains("=")).FirstOrDefault(y => y.Trim().ToLower().StartsWith("user"));
            if (u == null)
                throw new Exception($"ConnectionString {conName} is invalid !");
            sp = u.Split('=');
            return sp[1].Trim().ToUpper();
        }
        
        /// <summary>
        /// 调整表名称
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public static string SetTableName(string tableName)
        {
            var n2 = tableName.Replace("Ms", "Mon_");
            if (n2.EndsWith("History"))
                n2 = n2.Replace("History", "His");

            n2 = n2.ToUpper();
            return n2;
        }        
    }

通过这个设定,可以把所有实体的名字变成大写,并且可以根据需要增加前缀等,另外把实体模型的所有字段都改成大写,这样就不用纠结那些破事了。

posted @ 2018-04-17 17:15  流星夜  阅读(645)  评论(0编辑  收藏  举报