بررسی مسئله انتخاب اقدامکنندگان درون یک گرید در مراحل قبل و ارائه یک راهحل برای آن
طرح مسئله: فرض کنید در فرآیندی یکی از اقدام کنندگان فرآیند باید بتواند نام برخی افراد را در یک گرید قرار دهد تا فرم و دیتا برای کلیهی این افراد ارسال گردد.
یک راهحل: برای حل این مسئله یکی از راهکارها استفاده از دو فرآیند مجزاست، در فرآیند اول انتخاب گیرندگان صورت میگیرد و با روشی به ازای هر اقدامکننده، فرآیند دوم را اجرا کرده و فرم را برای اقدامکنندگان ارسال میکنیم. تصویر زیر نمونهای از دیاگرام این راهکار است:
همانطور که مشاهده میشود در اولین مرحله فرآیند “فرایند اول” فرم و دیتا پر میشود که تصویر فرم مربوطه در زیر آمده است:
ستون مورد نظر در این فرم، نام و نام خانوادگی است که حتماً باید از نوع سمت سازمانی دیدگاه باشد. پس نام اقدامکنندگان مرحله بعد باید در این ستون قرار بگیرد.
در مرحله بعد فرآیند با استفاده از یک فعالیت کدنویسی (Script Task) موارد زیر را انجام میدهیم:
- خواندن لیست اقدامکنندگان از گرید و قرار دادن آن درون یک متغیر DataTable
- شمارش تعداد ردیفهای گرید که در آنها اقدامکننده قرار داده شده است و نگهداری آن در یک متغیر
- تعریف متغیر شمارنده i و قراردادن مقدار اولیه 0 در آن.
در زیر نمونه کدی که کارهای فوق را انجام میدهند، مشاهده میکنید:
using System;
using System.Data;
using System.Data.SqlClient;
using Chargoon.Didgah.BPMS.CommonApi;
namespace Chargoon.Didgah.BPMS.Runtime
{
public class ScriptTask : IScriptTask
{
public IExecution Execution { get; set; }
public void Execute()
{
DataTable dt = new DataTable();
int counttable = 0;
SqlConnection conn = new SqlConnection();
conn.ConnectionString = Execution.GetConnectionString(“BPMSC601″);
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = @”SELECT TASKOWNER FROM bpm_KalaNavganShargh_Extra_SampleGrid
WHERE ParentGuid = @BusinessKey AND TASKOWNER is not null”;
cmd.Parameters.AddWithValue(“@BusinessKey”,Execution.GuidValue(“___BusinessKey”));
conn.Open();
dt.Load(cmd.ExecuteReader());
conn.Close();
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = conn;
cmd2.CommandText = @”SELECT COUNT(*) as counttable FROM bpm_KalaNavganShargh_Extra_SampleGrid
WHERE ParentGuid = @BusinessKey AND TASKOWNER is not null”;
cmd2.Parameters.AddWithValue(“@BusinessKey”,Execution.GuidValue(“___BusinessKey”));
conn.Open();
counttable = Convert.ToInt32(cmd2.ExecuteScalar());
conn.Close();
Execution.SetVariable(“dtVariable”,dt);
Execution.SetVariable(“counttable”,counttable);
Execution.SetVariable(“i”,0);
}
}
}
در ادامه فرآیند، در قسمت کدنویسی درگاه انحصاری (Exclusive Gateway) بررسی میکنیم که آیا تعداد رکوردهای جدول که دارای نام اقدامکننده هستند بیشتر از 0 هست یا خیر. اگر بیشتر بود فرآیند ادامه پیدا میکند.
using System;
using Chargoon.Didgah.BPMS.CommonApi;
namespace Chargoon.Didgah.BPMS.Runtime
{
public class ConditionalFlow : IConditionalFlow
{
public IExecution Execution { get; set; }
public bool Evaluate()
{
return Execution.IntegerValue(“counttable”)>0;
}
}
}
در ادامه، در قسمت کدنویسی درگاه انحصاری (Exclusive Gateway) بررسی میکنیم که آیا مقدار متغیر شمارنده از تعداد اقدامکنندگان کمتر باشد. این درگاه انحصاری (Exclusive Gateway)به محض آنکه مقدار متغیر شمارنده از تعداد اقدامکنندگان بزرگتر یا مساوی شد فرآیند را خاتمه میدهد.
using System;
using Chargoon.Didgah.BPMS.CommonApi;
namespace Chargoon.Didgah.BPMS.Runtime
{
public class ConditionalFlow : IConditionalFlow
{
public IExecution Execution { get; set; }
public bool Evaluate()
{ if(Execution.IntegerValue(“i”)<Execution.IntegerValue(“counttable”))
return true;
else
return false;
}
}
}
با ایجاد یک حلقه در فرآیند به ازای هر ردیف از جدول اقدامکننده را تشخیص داده، سپس فرایند دوم را اجرا و اقدامکننده را نیز به فرآیند دوم ارسال میکنیم.
برای این منظور از کد زیر استفاده میکنیم:
using System;
using System.Data;
using Chargoon.Didgah.BPMS.CommonApi;
namespace Chargoon.Didgah.BPMS.Runtime
{
public class ScriptTask : IScriptTask
{
public IExecution Execution { get; set; }
public void Execute()
{ int[] arrray = new int[Execution.DataTableValue(“dtVariable”).Rows.Count];
for (int i = 0; i < Execution.DataTableValue(“dtVariable”).Rows.Count; i++)
{
arrray[i] = Convert.ToInt32(Execution.DataTableValue(“dtVariable”).Rows[i][0]);
}
Execution.SetVariable(“abc”,arrray[Execution.IntegerValue(“i”)]);
}
}
}
در این کد همانطور که مشاهده میکنید، متغیری به نام abc حاوی نام اقدامکننده است.
همانطور که مشاهده میکنید، متغیر DataTableای که از مرحله قبل آمده را تبدیل به یک آرایه میکنیم، حال با استفاده از متغیر شمارنده، در هر بار اجرای حلقه در فرآیند، نام یکی از اقدامکنندگان از آرایه را استخراج کرده و از آن استفاده میکنیم.
با استفاده از کد زیر به ازای هر بار اجرای حلقه در فرآیند یکی به متغیر شمارنده اضافه میکنیم:
using System;
using Chargoon.Didgah.BPMS.CommonApi;
namespace Chargoon.Didgah.BPMS.Runtime
{
public class ScriptTask : IScriptTask
{
public IExecution Execution { get; set; }
public void Execute()
{
int temp = Execution.IntegerValue(“i”);
temp += 1;
Execution.SetVariable(“i”,temp);
}
}
}
حال با استفاده از یک رویداد پایان – پیام (End Event – message) فرآیند دوم را اجرا کرده و متغیر abc که حاوی نام اقدامکننده است را به فرآیند “فرایند دوم” ارسال میکنیم.
در فرآیند دوم تسکی که باید توسط اقدامکننده مورد نظر اجرا شود، اقدامکننده آن را از نوع کدنویسی انتخاب کرده و کد زیر را درون آن مینویسیم:
using System;
using Chargoon.Didgah.BPMS.CommonApi;
namespace Chargoon.Didgah.BPMS.Runtime
{
public class OwnerSelector : IOwnerSelector
{
public Iexecution Execution { get; set; }
public Owner GetOwner()
{
int UserStaffId = Execution.IntegerValue(“abc”);
return new Owner(UserStaffId);
}
}
}
نکته: درپیادهسازی این راهکار برای مشتریهای مختلف باید به نامهای جداول و ستونها و نام رشته اتصال دقت کرد؛ زیرا میتوانند از آنچه که در این اسکریپتها آورده شده است، متفاوت باشند.