Oracle根据实体类比对2个数据库结构差异(demo)
源起
在公司做项目时 经常出现 实体结构和线上的数据结构以及公司开发库数据结构不匹配的问题 但是又不能直接把开发库导入到生产库因为生产库已经有实际数据了 所以弄了一个小工具
此处只做记录用 demo级 未经过优化
依赖包
DapperExtensions.NetCore
Newtonsoft.Json
Oracle.ManagedDataAccess.Core
代码
新建一个名为 DBHelper 的 core 2.1 控制台程序 加入如下代码:(ps:实体类自备 本例中的实体类通过sqlsugar生成)
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using CommonHelper;
using Dapper;
using DapperExtensions;
using Newtonsoft.Json; namespace DBHelper
{
class Program
{
//实体模型路径
public static string modelpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DAO");
//实际数据结构获取源
public const string sourcedbconnStr = "Data Source=192.168.200.151/orcl;User ID=BG;Password=1;";
//要比较的数据库连接串
public const string todbconnStr = "Data Source=192.168.200.151/orcl;User ID=BG2019;Password=1;";
//缓存数据结构对象 如果存在 则不再去sourcedb中获取结构
public static string SaveFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sourceList.txt");
//生成的添加字段语句
public static string SqlSaveFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sql.txt");
public static List<string> GetAllTableName()
{
DirectoryInfo di = new DirectoryInfo(modelpath);
var res =new List<string>();
foreach (var item in di.GetFiles("*.cs"))
{
if (!item.Name.ToLower().StartsWith("base"))
res.Add(item.Name.Replace(item.Extension,""));
}
return res;
} static void Main(string[] args)
{
//记录所有的源数据库 数据结构
List<SourceSaveList> sl = new List<SourceSaveList>();
var tableNames = GetAllTableName();
if (File.Exists(SaveFilePath))
{
using (FileStream fs = new FileStream(SaveFilePath, FileMode.Open))
{
using (StreamReader sw = new StreamReader(fs))
{
var ss = sw.ReadToEnd();
sl = JsonConvert.DeserializeObject<List<SourceSaveList>>(ss);
}
}
}
else
{
var sourceDB = new DapperHelper(sourcedbconnStr);
foreach (var item in tableNames)
{
var source =sourceDB.Conn.Query<TableColumns>(
$"select column_name,data_type,data_length from user_tab_cols where table_name='{item}'")
.ToList();
sl.Add(new SourceSaveList() { cols = source, tableName = item });
}
}
var toDB = new DapperHelper(todbconnStr);
StringBuilder sb = new StringBuilder();
foreach (var item in tableNames)
{
var source = sl.First(c => c.tableName == item).cols;
var to=
toDB.Conn.Query<TableColumns>($"select column_name,data_type,data_length from user_tab_cols where table_name='{item}'")
.ToList();
if (source.Count == to.Count) continue;
foreach (var source_column in source)
{
if (to.Any(c => c.COLUMN_NAME == source_column.COLUMN_NAME)) continue;
switch (source_column.DATA_TYPE)
{ case "DATE":
sb.Append($"alter table {item} add {source_column.COLUMN_NAME} DATE;");
break;
case "TIMESTAMP(6)":
sb.Append($"alter table {item} add {source_column.COLUMN_NAME} TIMESTAMP(6);");
break;
case "TIMESTAMP":
sb.Append($"alter table {item} add {source_column.COLUMN_NAME} TIMESTAMP({source_column.DATA_LENGTH});");
break;
default:
sb.Append($"alter table {item} add {source_column.COLUMN_NAME} {source_column.DATA_TYPE}({source_column.DATA_LENGTH});");
break;
}
sb.Append("\r\n");
}
} using (FileStream fs = new FileStream(SaveFilePath, FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine(JsonConvert.SerializeObject(sl));
}
}
using (FileStream fs = new FileStream(SqlSaveFilePath, FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine(sb.ToString());
}
} }
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;
using DapperExtensions.Mapper;
using DapperExtensions.Sql;
using Oracle.ManagedDataAccess.Client; namespace CommonHelper
{
/// <summary>
/// dapper 帮助类
/// </summary>
public class DapperHelper
{
private Database Connection = null;
public DapperHelper(string conn)
{
var orcalConn = new OracleConnection(conn);
var orcaleconfig = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new OracleDialect());
var orcaleGenerator = new SqlGeneratorImpl(orcaleconfig);
Connection = new Database(orcalConn, orcaleGenerator);
}
public IDbConnection Conn
{
get
{
return Connection.Connection;
}
} }
}
CommonHelper.cs
using System;
using System.Collections.Generic;
using System.Text; namespace DBHelper
{
public class SourceSaveList
{
public string tableName { get; set; }
public List<TableColumns> cols { get; set; }
}
}
SourceSaveList.cs
using System;
using System.Collections.Generic;
using System.Text; namespace DBHelper
{
public class TableColumns
{
public string COLUMN_NAME { get; set; }
public string DATA_TYPE { get; set; }
public string DATA_LENGTH { get; set; }
}
}
TableColumns
说明
1.根据本例子的配置 在bin 目录中 新建DAO目录并将具体的模型拷入
2.将代码中的sourcedbconnStr 改为开发库连接串
2.将代码中的todbconnStr 改为需要生产库连接串
3.运行后会生成 sourceList.txt 用来保存开发库数据结构 用来支持程序结构拷贝到网络无法连接的生产数据库中
如果该文件存在 则不会再去获取开发库数据结构
4.sql.txt 该文件即为缺失字段的添加语句 如果不存在该表 目前会将所有字段均生成添加语句 此情况目前需要手工处理
Oracle根据实体类比对2个数据库结构差异(demo)的更多相关文章
- 【oracle】Enterprise Manager 无法连接到数据库实例。下面列出了组件的状态---个人解决方案
最近在学习Oracle,平常喜欢使用EM查看数据库状态,但是在最近突然发现EM连接不上Oracle数据库了,不知道问题出在哪里,只好卸载了重装.但是,在使用了几天以后,又出现了相同的问题,于是下决心将 ...
- oracle 实例名和服务名以及数据库名区别
一.数据库名什么是数据库名?数据库名就是一个数据库的标识,就像人的身份证号一样.他用参数DB_NAME表示,如果一台机器上装了多全数据库,那么每一个数据库都有一个数据库名.在数据库安装或创建完成之后, ...
- oracle所在磁盘空间不足导致了数据库异常
oracle所在磁盘空间不足导致了数据库异常.需要减小数据文件的大小来解决. 1.检查数据文件的名称和编号 select file#,name from v$datafile; 2.看哪个数据文件所占 ...
- EF Core中,通过实体类向SQL Server数据库表中插入数据后,实体对象是如何得到数据库表中的默认值的
我们使用EF Core的实体类向SQL Server数据库表中插入数据后,如果数据库表中有自增列或默认值列,那么EF Core的实体对象也会返回插入到数据库表中的默认值. 下面我们通过例子来展示,EF ...
- MyBatis中使用实体中使用枚举,数据库中使用数值
一.简介 本文主要讲MyBatis中使用实体中使用枚举,数据库中使用数值的解决方案.正常直接使用会报错,需要添加typeHandlers在mybatis-config.xml中. 二.解决方案 如下: ...
- Oracle、Db2、SqlServer、MySQL 数据库插入当前系统时间
做易买网项目,由于对数据库插入系统时间不了解,常常遇到的问题: 1.java.sql.SQLException: ORA-01861: 文字与格式字符串不匹配.原因:由于获取系统时间类型不对,应为sy ...
- Mybatis中resultMap的作用-解决实体类属性名和数据库字段不一致
解决实体类属性名和数据库字段不一致
- 使用jpa时,实体类有不存在数据库中的字段
使用jpa时,实体类有不存在数据库中的字段.在改属性上面加上这个注解@Transient就可以解决问题.
- Oracle 11g静默安装软件+手工创建数据库
由于是二次跳转+远程操作,无法使用图形界面,不能直接图形界面安装.采用静默安装软件+手工创建数据库的方式完成需求. 静默模式安装Oracle软件,配置监听程序 手工建库 检查各组件是否符合要求 1. ...
随机推荐
- python学习笔记(4)数据类型-元组
元组其实和列表一样,不一样的是,元组的值不能改变,一旦创建,就不能再改变了,比如说,要存数据库的连接信息,这个连接信息在程序运行中是不能被改变的,如果变了那数据库连不上了,就程序就完犊子了,这样的就可 ...
- python3多线程应用详解(第二卷:多线程到底是怎么工作的)
现在很多人都说用多线程工作快是因为多个不同任务可以同时执行,注意我说的是不同任务,要是重复做一件事达到相同效果就是画蛇添足了,其实这是个错误的说法,线程真正的本质是无法同时执行的.现在我们来看下多线程 ...
- python初认函数
今日所得 函数基本使用 函数的参数 函数的返回值 # 函数内要想返回给调用者值 必须用关键字return """ 不写return 只写return 写return No ...
- Java反射的应用 --- 内省
一.基础概念 内省(Introspector) 是Java 语言对 JavaBean 类属性.事件的一种缺省处理方法.Java JDK中提供了一套 API 用来访问某个属性的 getter/sette ...
- mysql 优化2 慢查询
默认情况下mysql不记录慢查询日志,需要在启动的时候指定 bin\mysqld.exe - -slow-query-log 通过慢查询日志定位执行效率较低的SQL语句.慢查询日志记录了所有执行时间超 ...
- 如何用Nginx解决跨域问题
一. 产生跨域的原因 1.浏览器限制 2.跨域 3.XHR(XMLHttpRequest)请求 二. 解决思路 解决跨域有多重,在这里主要讲用nginx解决跨域 1.JSONP 2.nginx代理 3 ...
- 吴裕雄--天生自然python学习笔记:Python3 网络编程
Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法. 高级别的网络 ...
- string删除与查找erase,find
s.erase( 指针位置 , 删除长度 ) 返回值修改后的string对象引用 find(string, int):第一个参数用来指示要查找的字符,第二个参数用来表示从字符串的何处开始查找子串(默认 ...
- [转载] 自定义标签,jsp调用java类
自己懒得做笔记,借用一下. 之前例子已经写好了,由于时间关系一直没有发布,这次带来的是关于taglib中的<tag>的基本功能已经介绍完毕了,在taglib中我们发现有一个标签叫做< ...
- Java WebSocket实现简易聊天室
一.Socket简介 Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求.Socket的英文原义是“孔”或“插座”,作为UNI ...