Oracle与EntityFramework(EF)的一些事情
时间:2022-03-15 07:37
概要
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;
}
}
通过这个设定,可以把所有实体的名字变成大写,并且可以根据需要增加前缀等,另外把实体模型的所有字段都改成大写,这样就不用纠结那些破事了。