Code
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 class ActivityTransfer : NativeActivity
{
// Define an activity input arguments of type string
[RequiredArgument]
[DefaultValue(null)]
public InArgument<string> PathAccess { get; set; }
[RequiredArgument]
[DefaultValue(null)]
public InArgument<string> PathdBase { get; set; }
[RequiredArgument]
[DefaultValue(null)]
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,row = null;
private string stringCommandAccessSQL = null;
private string stringCommanddBaseSQL = null;
private string readdBase = null;
private int i = 0;
// Container and Bookmark
Dictionary<string, int> values = null;
private Bookmark bookmark = null;
protected override void Execute(NativeActivityContext context)
{
string connectStringAccess = context.GetValue(PathAccess);
string connectStringdBase = context.GetValue(PathdBase);
try
{
i = 0;
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);
// Start bookmark
bookmark = context.CreateBookmark("Complete", ResumeBookmark, BookmarkOptions.MultipleResume);
}
catch (Exception ex) { ResultTransfer.Set(context, ex.ToString()); }
}
protected override bool CanInduceIdle {get { return true; }}
// ResumeBookmark
public void ResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj)
{
// Obj is not empty?
if (obj != null)
{
values = obj as Dictionary<string, int>;
// Tenth rows
for (int j = 0; j < dataTableAccess.Rows.Count / 10; j++)
{
// End recording
if (i >= dataTableAccess.Rows.Count)
{
adapterDbf.Update(dataTableDbf);
connectDbf.Close();
values["End"] = 1;
ResultTransfer.Set(context, "O.K.");
break;
}
row = dataTableAccess.Rows[i];
rowDbf = dataTableDbf.NewRow();
rowDbf["NUM"] = row[0];
rowDbf["FAM"] = row[1];
rowDbf["IM"] = row[2];
rowDbf["OT"] = row[3];
// Add row
dataTableDbf.Rows.Add(rowDbf);
++i;
}
// Set a complete and current number of Rows
values["Current_value"] = i;
values["CountRow"] = dataTableAccess.Rows.Count;
}
}
}
}
Bookmark Workflow - инструмент отображения динамики процесса.
Как отобразить динамику процесса, происходящего в WorkFlow, используя, например, стандартный компонент System.Windows.Forms.ProgressBar? Оказывается, довольно просто. Для этого можно применить обычную закладку - Bookmark. Известно, что работа с закладкой может сопровождаться передачей данных. Передположим, что отображение процесса происходит в одном потоке, а сам процесс выполняется в другом. Однако что может служить контейнером для обмена данными между потоками при работе с закладкой? Очень часто используется словарь - Dictionary.
Посмотрим, как реализовать это на практике. Для этого возьмем ранее описанный проект AccessTodBase и добавим на форму ProgressBar, он будет отображать процесс переписи данных из базы данных Access в dBase. Ну, а сам процесс переписи данных будет выполняться в дочернем потоке в ActivityTransfer. Представлен рабочий проект MS Visual Studio 2012 WorkFlow + Windows Forms Application. Кстати, который можно загрузить бесплатно.
1. ActivityTransfer.
Эта Activity переносит данные из таблицы Access в файл dBase. Что в ней нового? Во-первых, появилась закладка: bookmark. Затем, введен новый метод для выполнения закладки: ResumeBookmark. В этот метод перенесена функциональность по записи в таблицу dataTableDbf. Данные между потоками передаются через контейнер Dictionary values. И, наконец, обратите внимание, закладка создана как BookmarkOptions.MultipleResume. Добавлю к сказанному, что за одну итерацию пишется десятая часть содержимого таблицы Access. Можно, конечно, установить и другое число.
2. Основной поток, запуск WoprkFlow, Timer.
Текст приведен "как есть". Обратите внимание на обработчики событий wfApp.Idle и wfApp.Completed - это останов по закладке и завершение работы дочернего потока соответственно. В методе myTimer_Tick значения текущего и полного количества строк извлекаются из контейнера и отображаются на форме. Отображается и значение ProgressBar.
Visual Studio 2012 проект приложения можно загрузить Евгений Вересов.
25.04.2013 года.
|