AccessTodBase Windows Workflow
AccessTodBase Activity предназначена для экспорта данных из базы данных Access в Dbf файл. В чем смысл разработки этой программы?
Ведь в Access существует стандартная процедура экспорта данных. Дело в том, что при экспорте данных в Access есть проблема, числа, большие 15 знаков не могут быть нормально экспортированы в dBase, они урезаются до 15 символов. AccessTodBase решает эту проблему.
Программа интресна тем, что состоит только из Activity. Например, стандартный OpenFileDialog выполнен в виде Activity. Процедура преобразования из Access в DBf - это тоже Activity.
Интересно, на мой взгляд, и то, что все Activity помещены в единый Workflow, при запуске которого указывается код подлежащий выполнению Activity. Например, запуск Workflow c кодом операции "1" вызовет выполнение Activity, обеспечивающей диалог для выбора базы данных Access, запуск Workflow c кодом "2" - диалог для выбора dBase, "3" - вызов Activity, которая экспортирует данные из Access в dBase.
Надо понимать, что вызов любого Workflow - это запуск дочернего потока выпонения, каким бы методом мы его не вызывали, и естествено (или не естественно :)), надо подумать о синхронизации потоков.
Представлен рабочий проект MS Visual Studio 2012 WorkFlow + Windows Forms Application. Кстати, Workflow запускается из обычного Windows Forms приложения.
1. OpenFileDialog Activity. Выбор базы данных Access.
Ниже приведен текст стандартного OpenFileDialog для Access, выполненого в виде Activity. Диалог для dBase аналогичен.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.ComponentModel;
using System.Windows.Forms;
namespace AccessTodBase
{
public sealed class DialogAccess : CodeActivity
{
[RequiredArgument]
[DefaultValue(null)]
public InArgument<string> Drive { get; set; }
public OutArgument<string> OutPathAccess { get; set;}
private OpenFileDialog dialog;
protected override void Execute(CodeActivityContext context)
{
// Open Dialog
dialog = new OpenFileDialog();
dialog.InitialDirectory = context.GetValue(Drive);
dialog.Filter = "txt files (*.accdb)|*.accdb|All files (*.accdb)|*.accdb";
dialog.FilterIndex = 2;
dialog.RestoreDirectory = true;
if (dialog.ShowDialog() == DialogResult.OK)
{
OutPathAccess.Set(context, dialog.FileName);
}
}
}
}
2. Перенос данных из Access в dBase.
Ниже показана Activity выполняющая перенос данных из одной базы данных в другую.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.IO;
namespace AccessTodBase
{
public sealed class ActivityTransfer : CodeActivity
{
// Define an activity arguments of type string
[RequiredArgument]
[DefaultValue(null)]
public InArgument<string> PathAccess { get; set; }
public InArgument<string> PathdBase { get; set; }
public OutArgument<string> ResultTransfer { get; set; }
// Define private temporary
private OleDbConnection connectAccess, connectDbf = null;
private OleDbCommand commandAccess, commandDbf = null;
private OleDbDataAdapter adapterAccess, adapterDbf = null;
private OleDbDataReader reader = null;
private DataTable dataTableAccess = null;
private DataTable dataTableDbf = null;
private DataRow rowDbf = null;
private string stringCommandAccessSQL = null;
private string stringCommanddBaseSQL = null;
private string readdBase = null;
protected override void Execute(CodeActivityContext context)
{
string connectStringAccess = context.GetValue(PathAccess);
string connectStringdBase = context.GetValue(PathdBase);
try
{
if (String.IsNullOrEmpty(connectStringAccess)) throw new ArgumentNullException("Value", "File Name Access is null");
if (String.IsNullOrEmpty(connectStringdBase)) throw new ArgumentNullException("Value", "File Name dBase is null");
// Read data Access table
stringCommandAccessSQL = @"SELECT OutputTable.* FROM OutputTable";
connectAccess = new OleDbConnection(connectStringAccess);
connectAccess.Open();
commandAccess = new OleDbCommand(stringCommandAccessSQL, connectAccess);
adapterAccess = new OleDbDataAdapter(commandAccess);
reader = commandAccess.ExecuteReader();
dataTableAccess = new DataTable();
dataTableAccess.Load(reader);
connectAccess.Close();
// Connect dBase
stringCommanddBaseSQL = @"INSERT INTO INPUTP (NUM, FAM, IM, OT) VALUES (?, ?, ?, ?)";
readdBase = @"SELECT INPUTP.* FROM INPUTP";
connectDbf = new OleDbConnection(connectStringdBase);
connectDbf.Open();
commandDbf = new OleDbCommand(readdBase, connectDbf);
adapterDbf = new OleDbDataAdapter(commandDbf);
adapterDbf.InsertCommand = new OleDbCommand(stringCommanddBaseSQL, connectDbf);
adapterDbf.InsertCommand.Parameters.Add("@NUM", OleDbType.Numeric, 10, "NUM");
adapterDbf.InsertCommand.Parameters.Add("@FAM", OleDbType.Char, 40, "FAM");
adapterDbf.InsertCommand.Parameters.Add("@IM", OleDbType.Char, 40, "IM");
adapterDbf.InsertCommand.Parameters.Add("@OT", OleDbType.Char, 40, "OT");
dataTableDbf = new DataTable();
adapterDbf.Fill(dataTableDbf);
int i = 0;
foreach (DataRow row in dataTableAccess.Rows)
{
++i;
rowDbf = dataTableDbf.NewRow();
rowDbf["NUM"] = row[0];
rowDbf["FAM"] = row[1];
rowDbf["IM"] = row[2];
rowDbf["OT"] = row[3];
dataTableDbf.Rows.Add(rowDbf);
/* Debug
if (i == 100)
{
adapterDbf.Update(dataTableDbf);
connectDbf.Close();
Console.WriteLine("O.K.");
break;
}
*/
}
adapterDbf.Update(dataTableDbf);
connectDbf.Close();
ResultTransfer.Set(context, "O.K.");
}
catch (Exception ex)
{
ResultTransfer.Set(context, ex.ToString());
}
}
}
}
3. Полный текст программы, выпоняющей запуск Workflow и конкретных Activity.
Оператор должен выбрать пути нахождения баз данных и далее запустить процесс. Повторюсь, запуск Workflow выполняется из Windows Forms Application.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Activities;
using System.Threading;
using System.Timers;
using AccessTodBase;
namespace AccessTodBase
{
public partial class SetParametersForm : Form
{
WorkflowApplication wfApp = null;
AutoResetEvent waitHandler = null;
WorkFlowTransfer addwf = null;
WorkflowInvoker invoker = null;
private string connectStrAccess = string.Empty;
private string connectStrDbf = string.Empty;
private int codeActivity = 0;
public int endWorkFlow = 0;
public SetParametersForm()
{
InitializeComponent();
waitHandler = new AutoResetEvent(false);
}
// Start transfer data
private void Start_Click(object sender, EventArgs e)
{
try
{
// Set show gif file
pictureBoxWait.Visible = true;
endWorkFlow = 0;
// Define local temporary
string result = string.Empty;
string fileDirectory = String.Empty;
// Set code operation for ActivityTransfer
codeActivity = 3;
// Set Connect string for Access
connectStrAccess = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + textBoxAccess.Text;
// Set connect string for Dbf
int index = textBoxdBase.Text.LastIndexOf(@"\");
fileDirectory = textBoxdBase.Text.Substring(0, index + 1);
connectStrDbf = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + fileDirectory + @"; Extended Properties=dBASE IV";
// Set AutoResetEvent
waitHandler = new AutoResetEvent(false);
// Create WorkFlowTransfer
WorkFlowTransfer addwf = new WorkFlowTransfer()
{
PathAccessArgument = new InArgument<String>(connectStrAccess),
PathdBaseArgument = new InArgument<String>(connectStrDbf),
CodActivityArgument = new InArgument<int>(codeActivity)
};
// Create WorkflowApplication
wfApp = new WorkflowApplication(addwf);
// Create event handler wfApp.Completed
wfApp.Completed = (workflowApplicationCompletedEventArgs) =>
{
result = workflowApplicationCompletedEventArgs.Outputs["ResultWorkFlow"].ToString();
if (result != "O.K.") MessageBox.Show("Errot transfer Activity ...");
waitHandler.Set();
endWorkFlow = 1;
};
// Start workflow
myTimer.Enabled = true;
wfApp.Run();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
// Select Path Access DataBase
private void PathAccess_Click(object sender, EventArgs e)
{
try
{
// Set code Activity
codeActivity = 1;
addwf = new WorkFlowTransfer() { CodActivityArgument = new InArgument<int>(codeActivity) };
invoker = new WorkflowInvoker(addwf);
invoker.InvokeCompleted += delegate(object obj, InvokeCompletedEventArgs args)
{
textBoxAccess.Text = args.Outputs["ResultWorkFlow"].ToString();
waitHandler.Set();
};
invoker.InvokeAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error select Access", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
// Select path dBase DataBase
private void PathdBase_Click(object sender, EventArgs e)
{
try
{
// Set code Activity
codeActivity = 2;
addwf = new WorkFlowTransfer() { CodActivityArgument = new InArgument<int>(codeActivity) };
invoker = new WorkflowInvoker(addwf);
invoker.InvokeCompleted += delegate(object obj, InvokeCompletedEventArgs args)
{
textBoxdBase.Text = args.Outputs["ResultWorkFlow"].ToString();
waitHandler.Set();
};
invoker.InvokeAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error select dBase", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
// Tick metod timer
private void myTimer_Tick(object sender, EventArgs e)
{
if (endWorkFlow == 1)
{
pictureBoxWait.Visible = false;
myTimer.Enabled = false;
}
}
}
}
Visual Studio 2012 проект можно загрузить.
Евгений Вересов.
08.04.2013 года.
|