Windows service – Transfer data btw SQL Server and Oracle 9i
Hi
Windows service application is a great resource to automate tasks such as alter messages, data transfer between different databases and more.
Here is a Windows Service application that connects to SQL Server 2000, reads data and writes into two Oracle 9i Tables at specified start time and at interval time(i.e., every 12hrs or 24hrs) configured through app.config.
Both databases connection strings are configured through app.config along with windows service start time and interval time. when the start time is configured as 10AM and time interval is 12hrs, service starts at 10am and again at 10PM.
- Windows service is configurable from app.config
- SQL Server and Oracle Connection strings are read from app.config
- Service start time and Interval time is configurable from app.config xml file
- Service handles day light saving timings as well
- Note that DataTransfer() method is called from OnTimeElapsed method in service.
App.config <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <!--connectionStrings --> <add key="SqlconnStr" value="Data Source=mySource;
Initial Catalog=myCatalog; Integrated Security=True" /> <add key="oraConnection" value="provider=msdaora;
Data Source=mySource; User ID=logbook;Password=password;" /> <!-- Interval Time to start the service.
Note: 1 minute = 60,000 milliseconds
@@ 24Hrs = 86400000 Milli seconds --> <add key="intervalTime" value="60000" /> <!--Service Start Time to configure --> <add key="StartTime" value="1250" /> </appSettings>
Windows Service source
public partial class myService : ServiceBase { // This is the timer that will be used to execute TimeElapsed. System.Threading.Timer timer; // This will be the total number of minutes from midnight to
the time indicated in the app.config file. double minutesToStart = 0; // This is the last time the service was run. Set it to today,
but it may be changed in the OnStart method. DateTime lastRunDate = DateTime.Today; public myService() { InitializeComponent(); } protected override void OnStart(string[] args) { try { // Fetch the time of day to run the service from the app.config file. string startTimeString =
ConfigurationSettings.AppSettings["StartTime"].ToString(); // Instantiate a start time. DateTime startTime; // Try to parse out the time from the string retrieved
from the app.config. if (DateTime.TryParseExact(startTimeString, "HHmm",
CultureInfo.InvariantCulture,
DateTimeStyles.None, out startTime)) { // Get the total number of minutes from midnight represented by the // start time, and store it in the minutesToStart variable. minutesToStart = startTime.Subtract(startTime.Date).TotalMinutes; } // If the current date, plus the number of minutes we've
determined above hasn't passed yet, then set the lastRunDate
value to yesterday. if (DateTime.Today.AddMinutes(minutesToStart) > DateTime.Now) lastRunDate = DateTime.Today.AddDays(-1); // Start a timer. It should tick every second. System.Threading.Timer timer = new
System.Threading.Timer(OnElapsedTime, null, 1000, 1000); } catch (Exception ex) { System.Diagnostics.EventLog.WriteEntry("error in starting
my Service", ex.Message + Environment.NewLine + ex.StackTrace); } } protected override void OnStop() { //Nothing to do here } private void OnElapsedTime(object source) { // If today at midnight, plus the number of minutes defined
in the OnStart method has passed, and the lastRunDate is yesterday,
then set the lastRunDate to today and call TransferData(). if (DateTime.Today.AddMinutes(minutesToStart)
< DateTime.Now && DateTime.Today > lastRunDate) { lastRunDate = DateTime.Today; TransferData(); } } }
TransferData() method
/// <summary> /// Establish DB Connection and write data from SQL Server
/// Table into Oracle Tables /// records added/updated in last 24hrs /// </summary> /// <param name="sender"></param> /// <param name="e"></param> #region Dictionary<CraftKey, List<CraftValue>> sqlDataDictionary =
new Dictionary<CraftKey, List<CraftValue>>(); private List<CraftValue> _ProcessedCrafts = new List<CraftValue>(); private List<CraftKey> CraftKeys = new List<CraftKey>(); private void TransferData() { //Variables to store string workOrder, completion_date, conDateTest, assetNum, status,
workReq, craft, originator, OriginateDateStr, dateStr; DateTime originateDate; //Read connection String from web.config string connStr = ConfigurationSettings.AppSettings["SqlconnStr"].ToString(); //create connection passing connectionString //1) SqlConnection conn = new SqlConnection(connStr); OleDbConnection conn = new OleDbConnection(connStr); try { conn.Open(); } catch (Exception ex) { //write exception to LogEvent System.Diagnostics.EventLog.WriteEntry("WorkOrdersService",
ex.Message + Environment.NewLine + ex.StackTrace); } //Sqlcommand //2) SqlCommand cmd = conn.CreateCommand(); OleDbCommand cmd = conn.CreateCommand(); cmd.CommandText =
"SELECT
WKAW.WO,WKAW.CMPL_DATE,WKAW.ASSETNO,
WKAW.STATUS,WKAW.WORKREQ," + "WKAWAL.CRAFT,WKAWAL.CRAFT_CLO_FLAG," + "WKAW.ORG_DATE,WKAW.ORIGINATOR " + "FROM WKAW,WKAWAL" + " WHERE " + "WKAW.WO = WKAWAL.WO" + " AND " + "WKAW.STATUS <> 'CLO'" + " AND " + "WKAW.ORG_DATE BETWEEN SYSDATE - 1 AND SYSDATE " + " ORDER BY WKAWAL.CRAFT, WKAW.ORG_DATE"; //DataReader OleDbDataAdapter adapter = new OleDbDataAdapter(cmd); //3) SqlDataAdapter adapter = new SqlDataAdapter(cmd); DataTable sqlData = new DataTable(); adapter.Fill(sqlData); EnsureNoDuplicates(sqlData); PrepareProcessedCrafts(); for (int i = 0; i < _ProcessedCrafts.Count; i++) { CraftValue value = _ProcessedCrafts[i]; workOrder = value.WorkOrder; assetNum = value.AssetNum; workReq = value.WorkReq; craft = value.Craft; originateDate = value.NewDate; originator = value.Originator; //Open a Oledb connection to Opralog using (OleDbConnection connection = new OleDbConnection(
ConfigurationSettings.AppSettings["opralogConnection"].ToString())) { //convert Date to String format OriginateDateStr = originateDate.ToString("dd-MMM-yyyy HH:mm:ss"); dateStr = originateDate.ToString("dd-MMM-yyyy HH:mm:ss"); //Create oledb command instance OleDbCommand command = new OleDbCommand(); //create an isntance of Transaction OleDbTransaction transaction = null; // Set the Connection to the new OleDbConnection command.Connection = connection; // Open the connection and execute the transaction try { //open connection connection.Open(); //Start a local transaction with ReadCommitted isolation level transaction = connection.BeginTransaction(IsolationLevel.
ReadCommitted); // Assign transaction object for a pending local transaction. command.Connection = connection; command.Transaction = transaction; //data_no column int data_no = 1; //Insert itno external_event_occurrances command.CommandText = "INSERT INTO external_event_occurrances
(dcs_link,event_timestamp) VALUES('" + "DPWO_" + craft + "',
to_date('" + OriginateDateStr + "', 'dd-mon-yyyy hh24:mi:ss'))"; command.ExecuteNonQuery(); //Insert into external_event_data command.CommandText = "INSERT INTO external_event_data(dcs_link,
event_timestamp,data_no,col_data) VALUES('" + "DPWO_" + craft + "',
to_date('" + OriginateDateStr + "', 'dd-mon-yyyy hh24:mi:ss'), '"
+ data_no + "' , '" + workOrder + "')"; command.ExecuteNonQuery(); data_no = data_no + 1; command.CommandText = "INSERT INTO external_event_data(dcs_link,
event_timestamp,data_no,col_data) VALUES('" + "DPWO_" + craft + "',
to_date('" + OriginateDateStr + "', 'dd-mon-yyyy hh24:mi:ss'), '"
+ data_no + "' , '" + assetNum + "')"; command.ExecuteNonQuery(); data_no = data_no + 1; command.CommandText = "INSERT INTO external_event_data(dcs_link,
event_timestamp,data_no,col_data) VALUES('" + "DPWO_" + craft + "',
to_date('" + OriginateDateStr + "', 'dd-mon-yyyy hh24:mi:ss'), '" +
data_no + "' , '" + workReq + "')"; command.ExecuteNonQuery(); data_no = data_no + 1; command.CommandText = "INSERT INTO external_event_data
(dcs_link, event_timestamp,data_no,col_data) VALUES('" + "DPWO_"
+ craft + "', to_date('" + OriginateDateStr + "',
'dd-mon-yyyy hh24:mi:ss'), '" + data_no + "' ,'" + dateStr + "')"; command.ExecuteNonQuery(); data_no = data_no + 1; command.CommandText = "INSERT INTO external_event_data(dcs_link,
event_timestamp,data_no,col_data) VALUES('" + "DPWO_" + craft + "',
to_date('" + OriginateDateStr + "', 'dd-mon-yyyy hh24:mi:ss'), '"
+ data_no + "' , '" + originator + "')"; command.ExecuteNonQuery(); //commit the transaction transaction.Commit(); //Response.Write("\nRecords inserted into both Tables"); } catch (Exception ex) { //write exception to Event Log System.Diagnostics.EventLog.WriteEntry("WorkOrdersService",
ex.Message + Environment.NewLine + ex.StackTrace); // Attempt to roll back the transaction. try { transaction.Rollback(); } catch { //Do nothing here. Releases resources } } } } // connection conn.Close(); } private void PrepareProcessedCrafts() { for (int i = 0; i < CraftKeys.Count; i++) { List<CraftValue> values = sqlDataDictionary[CraftKeys[i]]; for (int j = 0; j < values.Count; j++) { _ProcessedCrafts.Add(values[j]); } } } /// <summary> /// Handling the data for any duplicates and /// processing the data not to have it /// </summary> /// <param name="sqlData"></param> internal void EnsureNoDuplicates(DataTable sqlData) { for (int i = 0; i < sqlData.Rows.Count; i++) { List<CraftValue> values; DataRow row = sqlData.Rows[i]; CraftKey key = new CraftKey(); key.Craft = row["craft"].ToString(); key.OrgDate = DateTime.Parse(row["org_date"].ToString()); values = GetCraftValues(key); if (values != null) { //Means we have a duplicate //Make existing seconds value to zero //For each of value make seconds starting from zero //so it always gives guarantee that 59 records are not duplicates for (int j = 0; j < values.Count; j++) { TimeSpan span = new TimeSpan(0, 0, 0, values[j].NewDate.Second); values[j].NewDate = values[j].NewDate.Subtract(span).AddSeconds(j); } //Now Insert our current record with one second CraftValue newValue = BuildCraftValue(values.Count, row); values.Add(newValue); //here we need not to add dictionary as we are using the item
//which the dictionary already has } else { //If we do not have the craft with the specified date already
//build the key and add it to dictionary CraftValue newValue = BuildCraftValue(key.OrgDate.Second, row); values = new List<CraftValue>(); values.Add(newValue); sqlDataDictionary.Add(key, values); //Add it to list of CraftKeys so that we can loop through it later CraftKeys.Add(key); } } } private List<CraftValue> GetCraftValues(CraftKey key) { for (int i = 0; i < CraftKeys.Count; i++) { if (CraftKeys[i].Craft == key.Craft &&
CraftKeys[i].OrgDate == key.OrgDate) { return sqlDataDictionary[CraftKeys[i]]; } } return null; } private CraftValue BuildCraftValue(int secondValue, DataRow row) { CraftValue value = new CraftValue(); value.Craft = row["craft"].ToString(); value.AssetNum = row["assetno"].ToString(); value.WorkOrder = row["wo"].ToString(); value.WorkReq = row["workreq"].ToString(); DateTime date = (DateTime)row["org_date"]; value.NewDate = date.Subtract(new
TimeSpan(date.Second)).AddSeconds(secondValue); value.Originator = row["originator"].ToString(); return value; } class CraftKey { private string _craft; public string Craft { get { return _craft; } set { _craft = value; } } private DateTime _orgDate; public DateTime OrgDate { get { return _orgDate; } set { _orgDate = value; } } } class CraftValue { private string _workOrder; private string _assetNum; private string _originator; private string _workReq; private DateTime _newDate; public string WorkOrder { get { return _workOrder; } set { _workOrder = value; } } public string AssetNum { get { return _assetNum; } set { _assetNum = value; } } private string _craft; public string Craft { get { return _craft; } set { _craft = value; } } public string Originator { get { return _originator; } set { _originator = value; } } public string WorkReq { get { return _workReq; } set { _workReq = value; } } public DateTime NewDate { get { return _newDate; } set { _newDate = value; } } } #endregion } }
References
Creating windows service in C#
Debugging Windows Service Applications