entity 오류로인해 제거해야해서 . 제거전 백업
This commit is contained in:
131
DBMigration/Forms/ConnectionForm.cs
Normal file
131
DBMigration/Forms/ConnectionForm.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using DBMigration.Models;
|
||||
|
||||
namespace DBMigration.Forms
|
||||
{
|
||||
public partial class ConnectionForm : Form
|
||||
{
|
||||
public ConnectionInfo ConnectionInfo { get; private set; }
|
||||
|
||||
public ConnectionForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Load += ConnectionForm_Load;
|
||||
}
|
||||
|
||||
private void ConnectionForm_Load(object? sender, EventArgs e)
|
||||
{
|
||||
UpdateCredentialsFields();
|
||||
this.txtServer.Text = "10.131.15.18";
|
||||
this.txtDatabase.Text = "EE";
|
||||
this.txtUserId.Text = "eeuser";
|
||||
this.txtPassword.Text = "Amkor123!";
|
||||
this.chkWindowsAuth.Checked = false;
|
||||
}
|
||||
|
||||
private void UpdateCredentialsFields()
|
||||
{
|
||||
bool isWindowsAuth = chkWindowsAuth.Checked;
|
||||
txtUserId.Enabled = !isWindowsAuth;
|
||||
txtPassword.Enabled = !isWindowsAuth;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.txtServer = new TextBox();
|
||||
this.txtDatabase = new TextBox();
|
||||
this.txtUserId = new TextBox();
|
||||
this.txtPassword = new TextBox();
|
||||
this.chkWindowsAuth = new CheckBox();
|
||||
this.btnConnect = new Button();
|
||||
this.btnCancel = new Button();
|
||||
this.SuspendLayout();
|
||||
|
||||
// txtServer
|
||||
this.txtServer.Location = new Point(12, 12);
|
||||
this.txtServer.Size = new Size(200, 23);
|
||||
this.txtServer.PlaceholderText = "서버 이름";
|
||||
|
||||
// txtDatabase
|
||||
this.txtDatabase.Location = new Point(12, 41);
|
||||
this.txtDatabase.Size = new Size(200, 23);
|
||||
this.txtDatabase.PlaceholderText = "데이터베이스 이름";
|
||||
|
||||
// txtUserId
|
||||
this.txtUserId.Location = new Point(12, 70);
|
||||
this.txtUserId.Size = new Size(200, 23);
|
||||
this.txtUserId.PlaceholderText = "사용자 ID";
|
||||
|
||||
// txtPassword
|
||||
this.txtPassword.Location = new Point(12, 99);
|
||||
this.txtPassword.Size = new Size(200, 23);
|
||||
this.txtPassword.PasswordChar = '*';
|
||||
this.txtPassword.PlaceholderText = "비밀번호";
|
||||
|
||||
// chkWindowsAuth
|
||||
this.chkWindowsAuth.Location = new Point(12, 128);
|
||||
this.chkWindowsAuth.Size = new Size(200, 23);
|
||||
this.chkWindowsAuth.Text = "Windows 인증 사용";
|
||||
this.chkWindowsAuth.CheckedChanged += (s, e) => UpdateCredentialsFields();
|
||||
|
||||
// btnConnect
|
||||
this.btnConnect.Location = new Point(12, 157);
|
||||
this.btnConnect.Size = new Size(95, 23);
|
||||
this.btnConnect.Text = "연결";
|
||||
this.btnConnect.Click += BtnConnect_Click;
|
||||
|
||||
// btnCancel
|
||||
this.btnCancel.Location = new Point(117, 157);
|
||||
this.btnCancel.Size = new Size(95, 23);
|
||||
this.btnCancel.Text = "취소";
|
||||
this.btnCancel.Click += BtnCancel_Click;
|
||||
|
||||
// ConnectionForm
|
||||
this.ClientSize = new Size(224, 192);
|
||||
this.Controls.AddRange(new Control[] {
|
||||
this.txtServer,
|
||||
this.txtDatabase,
|
||||
this.txtUserId,
|
||||
this.txtPassword,
|
||||
this.chkWindowsAuth,
|
||||
this.btnConnect,
|
||||
this.btnCancel
|
||||
});
|
||||
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.StartPosition = FormStartPosition.CenterParent;
|
||||
this.Text = "데이터베이스 연결";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
}
|
||||
|
||||
private void BtnConnect_Click(object? sender, EventArgs e)
|
||||
{
|
||||
ConnectionInfo = new ConnectionInfo
|
||||
{
|
||||
ServerName = txtServer.Text,
|
||||
DatabaseName = txtDatabase.Text,
|
||||
UserId = txtUserId.Text,
|
||||
Password = txtPassword.Text,
|
||||
UseWindowsAuthentication = chkWindowsAuth.Checked
|
||||
};
|
||||
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void BtnCancel_Click(object? sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
}
|
||||
|
||||
private TextBox txtServer;
|
||||
private TextBox txtDatabase;
|
||||
private TextBox txtUserId;
|
||||
private TextBox txtPassword;
|
||||
private CheckBox chkWindowsAuth;
|
||||
private Button btnConnect;
|
||||
private Button btnCancel;
|
||||
}
|
||||
}
|
||||
67
DBMigration/Forms/MainForm.Designer.cs
generated
Normal file
67
DBMigration/Forms/MainForm.Designer.cs
generated
Normal file
@@ -0,0 +1,67 @@
|
||||
namespace DBMigration.Forms
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.treeObjects = new System.Windows.Forms.TreeView();
|
||||
this.btnConnectSource = new System.Windows.Forms.Button();
|
||||
this.btnMigrate = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// treeObjects
|
||||
//
|
||||
this.treeObjects.Location = new System.Drawing.Point(12, 12);
|
||||
this.treeObjects.Name = "treeObjects";
|
||||
this.treeObjects.Size = new System.Drawing.Size(300, 400);
|
||||
this.treeObjects.TabIndex = 0;
|
||||
//
|
||||
// btnConnectSource
|
||||
//
|
||||
this.btnConnectSource.Location = new System.Drawing.Point(12, 418);
|
||||
this.btnConnectSource.Name = "btnConnectSource";
|
||||
this.btnConnectSource.Size = new System.Drawing.Size(150, 30);
|
||||
this.btnConnectSource.TabIndex = 1;
|
||||
this.btnConnectSource.Text = "소스 DB 연결";
|
||||
this.btnConnectSource.UseVisualStyleBackColor = true;
|
||||
this.btnConnectSource.Click += new System.EventHandler(this.btnConnectSource_Click);
|
||||
//
|
||||
// btnMigrate
|
||||
//
|
||||
this.btnMigrate.Location = new System.Drawing.Point(168, 418);
|
||||
this.btnMigrate.Name = "btnMigrate";
|
||||
this.btnMigrate.Size = new System.Drawing.Size(144, 30);
|
||||
this.btnMigrate.TabIndex = 2;
|
||||
this.btnMigrate.Text = "마이그레이션 시작";
|
||||
this.btnMigrate.UseVisualStyleBackColor = true;
|
||||
this.btnMigrate.Click += new System.EventHandler(this.btnMigrate_Click);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(324, 461);
|
||||
this.Controls.Add(this.btnMigrate);
|
||||
this.Controls.Add(this.btnConnectSource);
|
||||
this.Controls.Add(this.treeObjects);
|
||||
this.Name = "MainForm";
|
||||
this.Text = "DB Migration Tool";
|
||||
this.ResumeLayout(false);
|
||||
}
|
||||
|
||||
private System.Windows.Forms.TreeView treeObjects;
|
||||
private System.Windows.Forms.Button btnConnectSource;
|
||||
private System.Windows.Forms.Button btnMigrate;
|
||||
}
|
||||
}
|
||||
184
DBMigration/Forms/MainForm.cs
Normal file
184
DBMigration/Forms/MainForm.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
using DBMigration.Models;
|
||||
using DBMigration.Services;
|
||||
|
||||
namespace DBMigration.Forms
|
||||
{
|
||||
public partial class MainForm : Form
|
||||
{
|
||||
private readonly DatabaseService _databaseService;
|
||||
private readonly MigrationService _migrationService;
|
||||
private ConnectionInfo? _sourceConnection;
|
||||
private ConnectionInfo? _targetConnection;
|
||||
private List<DatabaseObject>? _databaseObjects;
|
||||
private readonly CancellationTokenSource _cancellationTokenSource;
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
_databaseService = new DatabaseService();
|
||||
_migrationService = new MigrationService();
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
_databaseObjects = new List<DatabaseObject>();
|
||||
}
|
||||
|
||||
private async void btnConnectSource_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var form = new ConnectionForm())
|
||||
{
|
||||
if (form.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
_sourceConnection = form.ConnectionInfo;
|
||||
await LoadDatabaseObjectsAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadDatabaseObjectsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
btnConnectSource.Enabled = false;
|
||||
treeObjects.Nodes.Clear();
|
||||
|
||||
// 테이블, 뷰, 프로시저 노드 생성
|
||||
var tableNode = treeObjects.Nodes.Add("Tables");
|
||||
var viewNode = treeObjects.Nodes.Add("Views");
|
||||
var procNode = treeObjects.Nodes.Add("Stored Procedures");
|
||||
|
||||
// 테이블 로드
|
||||
tableNode.Nodes.Add("Loading...");
|
||||
treeObjects.ExpandAll();
|
||||
await LoadTablesAsync(tableNode);
|
||||
|
||||
// 뷰 로드
|
||||
viewNode.Nodes.Add("Loading...");
|
||||
await LoadViewsAsync(viewNode);
|
||||
|
||||
// 프로시저 로드
|
||||
procNode.Nodes.Add("Loading...");
|
||||
await LoadProceduresAsync(procNode);
|
||||
|
||||
btnConnectSource.Enabled = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"데이터베이스 객체 로드 중 오류 발생: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
btnConnectSource.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadTablesAsync(TreeNode parentNode)
|
||||
{
|
||||
try
|
||||
{
|
||||
parentNode.Nodes.Clear();
|
||||
parentNode.Nodes.Add("Loading...");
|
||||
|
||||
await foreach (var table in _databaseService.GetTables(_sourceConnection!))
|
||||
{
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
var node = new TreeNode($"{table.Schema}.{table.Name}")
|
||||
{
|
||||
Tag = table,
|
||||
Checked = table.IsSelected
|
||||
};
|
||||
|
||||
parentNode.Nodes.Add(node);
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
parentNode.Nodes.Clear();
|
||||
parentNode.Nodes.Add($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadViewsAsync(TreeNode parentNode)
|
||||
{
|
||||
try
|
||||
{
|
||||
parentNode.Nodes.Clear();
|
||||
parentNode.Nodes.Add("Loading...");
|
||||
|
||||
await foreach (var view in _databaseService.GetViews(_sourceConnection!))
|
||||
{
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
var node = new TreeNode($"{view.Schema}.{view.Name}")
|
||||
{
|
||||
Tag = view,
|
||||
Checked = view.IsSelected
|
||||
};
|
||||
|
||||
parentNode.Nodes.Add(node);
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
parentNode.Nodes.Clear();
|
||||
parentNode.Nodes.Add($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadProceduresAsync(TreeNode parentNode)
|
||||
{
|
||||
try
|
||||
{
|
||||
parentNode.Nodes.Clear();
|
||||
parentNode.Nodes.Add("Loading...");
|
||||
|
||||
await foreach (var proc in _databaseService.GetProcedures(_sourceConnection!))
|
||||
{
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
var node = new TreeNode($"{proc.Schema}.{proc.Name}")
|
||||
{
|
||||
Tag = proc,
|
||||
Checked = proc.IsSelected
|
||||
};
|
||||
|
||||
parentNode.Nodes.Add(node);
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
parentNode.Nodes.Clear();
|
||||
parentNode.Nodes.Add($"Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||
{
|
||||
_cancellationTokenSource.Cancel();
|
||||
base.OnFormClosing(e);
|
||||
}
|
||||
|
||||
private void btnMigrate_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_targetConnection == null)
|
||||
{
|
||||
MessageBox.Show("대상 데이터베이스 연결 정보를 먼저 설정하세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedObjects = _databaseObjects.Where(o => o.IsSelected).ToList();
|
||||
if (selectedObjects.Count == 0)
|
||||
{
|
||||
MessageBox.Show("마이그레이션할 객체를 선택하세요.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
using (var form = new ProgressForm(selectedObjects, _sourceConnection, _targetConnection))
|
||||
{
|
||||
form.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
120
DBMigration/Forms/MainForm.resx
Normal file
120
DBMigration/Forms/MainForm.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
56
DBMigration/Forms/ProgressForm.Designer.cs
generated
Normal file
56
DBMigration/Forms/ProgressForm.Designer.cs
generated
Normal file
@@ -0,0 +1,56 @@
|
||||
namespace DBMigration.Forms
|
||||
{
|
||||
partial class ProgressForm
|
||||
{
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.progressBar = new System.Windows.Forms.ProgressBar();
|
||||
this.logTextBox = new System.Windows.Forms.TextBox();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// progressBar
|
||||
//
|
||||
this.progressBar.Location = new System.Drawing.Point(12, 12);
|
||||
this.progressBar.Name = "progressBar";
|
||||
this.progressBar.Size = new System.Drawing.Size(300, 23);
|
||||
this.progressBar.TabIndex = 0;
|
||||
//
|
||||
// logTextBox
|
||||
//
|
||||
this.logTextBox.Location = new System.Drawing.Point(12, 41);
|
||||
this.logTextBox.Multiline = true;
|
||||
this.logTextBox.Name = "logTextBox";
|
||||
this.logTextBox.ReadOnly = true;
|
||||
this.logTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.logTextBox.Size = new System.Drawing.Size(300, 200);
|
||||
this.logTextBox.TabIndex = 1;
|
||||
//
|
||||
// ProgressForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(324, 253);
|
||||
this.Controls.Add(this.logTextBox);
|
||||
this.Controls.Add(this.progressBar);
|
||||
this.Name = "ProgressForm";
|
||||
this.Text = "마이그레이션 진행 상황";
|
||||
this.Load += new System.EventHandler(this.ProgressForm_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
}
|
||||
|
||||
private System.Windows.Forms.ProgressBar progressBar;
|
||||
private System.Windows.Forms.TextBox logTextBox;
|
||||
}
|
||||
}
|
||||
107
DBMigration/Forms/ProgressForm.cs
Normal file
107
DBMigration/Forms/ProgressForm.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using DBMigration.Models;
|
||||
using DBMigration.Services;
|
||||
using Microsoft.Data.SqlClient;
|
||||
|
||||
namespace DBMigration.Forms
|
||||
{
|
||||
public partial class ProgressForm : Form
|
||||
{
|
||||
private readonly List<DatabaseObject> _objects;
|
||||
private readonly ConnectionInfo _source;
|
||||
private readonly ConnectionInfo _target;
|
||||
private readonly MigrationService _migrationService;
|
||||
|
||||
public ProgressForm(List<DatabaseObject> objects, ConnectionInfo source, ConnectionInfo target)
|
||||
{
|
||||
InitializeComponent();
|
||||
_objects = objects;
|
||||
_source = source;
|
||||
_target = target;
|
||||
_migrationService = new MigrationService();
|
||||
|
||||
progressBar.Maximum = _objects.Count;
|
||||
}
|
||||
|
||||
private async void ProgressForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
await Task.Run(() => MigrateObjects());
|
||||
}
|
||||
|
||||
private void MigrateObjects()
|
||||
{
|
||||
foreach (var obj in _objects)
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateProgress($"마이그레이션 시작: {obj.Type} {obj.Schema}.{obj.Name}");
|
||||
|
||||
if (obj.Type == "TABLE")
|
||||
{
|
||||
_migrationService.MigrateTable(obj, _source, _target);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 뷰나 프로시저의 경우 스크립트만 실행
|
||||
ExecuteScript(obj.Definition, _target);
|
||||
}
|
||||
|
||||
UpdateProgress($"완료: {obj.Type} {obj.Schema}.{obj.Name}");
|
||||
UpdateProgressBar();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UpdateProgress($"오류 발생: {obj.Type} {obj.Schema}.{obj.Name}");
|
||||
UpdateProgress($"에러 메시지: {ex.Message}");
|
||||
|
||||
if (MessageBox.Show(
|
||||
$"{obj.Type} {obj.Schema}.{obj.Name} 마이그레이션 중 오류가 발생했습니다.\n계속 진행하시겠습니까?",
|
||||
"오류",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Error) == DialogResult.No)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.Show("마이그레이션이 완료되었습니다.", "완료", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
DialogResult = DialogResult.OK;
|
||||
}
|
||||
|
||||
private void UpdateProgress(string message)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action<string>(UpdateProgress), message);
|
||||
return;
|
||||
}
|
||||
|
||||
logTextBox.AppendText(message + Environment.NewLine);
|
||||
logTextBox.SelectionStart = logTextBox.TextLength;
|
||||
logTextBox.ScrollToCaret();
|
||||
}
|
||||
|
||||
private void UpdateProgressBar()
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(UpdateProgressBar));
|
||||
return;
|
||||
}
|
||||
|
||||
progressBar.Value++;
|
||||
}
|
||||
|
||||
private void ExecuteScript(string script, ConnectionInfo connection)
|
||||
{
|
||||
using (var conn = new SqlConnection(connection.GetConnectionString()))
|
||||
{
|
||||
conn.Open();
|
||||
using (var cmd = new SqlCommand(script, conn))
|
||||
{
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user