abl to c sharp conversion user group presentation

22
Ahmed Hamidi Lead Software Architect ABL to C# BPM Conversion

Upload: zabed-hossain

Post on 16-Jul-2016

45 views

Category:

Documents


10 download

TRANSCRIPT

Page 1: Abl to c Sharp Conversion User Group Presentation

Ahmed HamidiLead Software Architect

ABL to C# BPM Conversion

Page 2: Abl to c Sharp Conversion User Group Presentation

Topics

3 ABL to C# conversion exercisesCommon ErrorsCommon Progress Commands

Questions

Page 3: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Exercise 1 – Default Field

• ABL Code:FOR FIRST ttOrderHed WHERE ttOrderHed.RowMod <> “” NO-LOCK.

ASSIGN ttOrderHed.OrderDate = TODAY. END.

• C# Code: foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in ttOrderHed where ttOrderHed_Row.RowMod != “” select ttOrderHed_Row)) { var ttOrderHedRow = ttOrderHed_iterator; ttOrderHedRow.OrderDate = DateTime.Now; }

This example will default today’s date in Sale Order Entry, after Get New is called.- post processing method directive on Sales Order – GetNew.

Page 4: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Exercise 1 – Translation

• ABL Code:FOR FIRST ttOrderHed WHERE ttOrderHed.RowMod <> “” NO-LOCK.

ASSIGN ttOrderHed.OrderDate = TODAY. END.

• C# Code: foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in

ttOrderHed where ttOrderHed_Row.RowMod != “” select ttOrderHed_Row)) { var ttOrderHedRow = ttOrderHed_iterator; ttOrderHedRow.OrderDate = DateTime.Now; }

Page 5: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Exercise 1 – ERROR

Converted C# syntax: foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in

ttOrderHed where ttOrderHed_Row.RowMod != “” select ttOrderHed_Row))

Proper C# syntax: foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in

ttOrderHed where String.Equals( ttOrderHed_Row.RowMod, “”) select ttOrderHed_Row))

Page 6: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Exercise 2 – Cross reference validation

• ABL Code:FOR FIRST ttCustomer WHERE ttCustomer.RowMod = “A” NO-LOCK.

IF CAN-FIND(UD40 WHERE UD40.Company = CUR-COMP AND UD40.Key1 = ttCustomer.State AND UD40.Key2 = ‘’ AND UD40.Key3 = ‘’ AND UD40.Key4 = ‘’ AND UD40.Key5 = ‘’) = FALSE THEN

DO: {lib/PublishEx.i &ExMsg = "'Invalid State'"} {&THROW_PUBLIC}. END. END .• C# Code:

object THROW_PUBLIC = null;Ice.Tables.UD40 UD40; foreach(var ttCustomer_iterator in(from ttCustomer_Row in ttCustomer where ttCustomer_Row.RowMod == “A” select ttCustomer_Row)) { var ttCustomerRow = ttCustomer_iterator; if(((from UD40_Row in Db.UD40 where UD40_Row.Company == Session.CompanyID && UD40_Row.Key1 == ttCustomerRow.State && UD40_Row.Key2 == ‘’ && UD40_Row.Key3 == ‘’ && UD40_Row.Key4 == ‘’ && UD40_Row.Key5 == ‘’ select UD40_Row).Count() != 0) == false) {CallContext.Current.ExceptionManager.AddBLException("Invalid State"); THROW_PUBLIC = null; } }

This example will validate the State entered in the Customer Maintenance screen, which is free form, against a UD table.PreProcessing directive on Customer Update method

Page 7: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Exercise 2 – Translation

• ABL Code:FOR FIRST ttCustomer WHERE ttCustomer.RowMod = “A” NO-LOCK.

IF CAN-FIND(UD40 WHERE UD40.Company = CUR-COMP AND UD40.Key1 = ttCustomer.State AND UD40.Key2 = ‘’ AND UD40.Key3 = ‘’ AND UD40.Key4 = ‘’ AND UD40.Key5 = ‘’) = FALSE THEN

DO: {lib/PublishEx.i &ExMsg = "'Invalid State'"} {&THROW_PUBLIC}. END. END .• C# Code:

object THROW_PUBLIC = null;Ice.Tables.UD40 UD40;

foreach(var ttCustomer_iterator in(from ttCustomer_Row in ttCustomer where ttCustomer_Row.RowMod == “A” select ttCustomer_Row)) { var ttCustomerRow = ttCustomer_iterator; if(((from UD40_Row in Db.UD40 where UD40_Row.Company == Session.CompanyID

&& UD40_Row.Key1 == ttCustomerRow.State && UD40_Row.Key2 == ‘’ && UD40_Row.Key3 == ‘’ && UD40_Row.Key4 == ‘’ && UD40_Row.Key5 == ‘’

select UD40_Row).Count() != 0) == false) {

CallContext.Current.ExceptionManager.AddBLException("Invalid State"); THROW_PUBLIC = null; } }

Page 8: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Exercise 3 – Run Persistent

ABL:{Bpm/Bpm.i &OBJECT_NAME=AbcCode}{bo/UD01/UD01_ds.i}procedure UpdateBefore: define input-output parameter table for ttAbcCode.{&TRY_PRIVATE} define variable hUD01 as handle. find first ttAbccode no-lock no-error. RUN bo\UD01\UD01.p PERSISTENT SET hUD01. IF VALID-HANDLE (hUD01) THEN DO: /*Create new record*/ RUN GETANEWUD01 IN hUD01 ( {&input-output_dataset_UD01DataSet} ) NO-ERROR. find first ttUD01 where ttUD01.ROWMOD = 'A' no-lock no-error. IF available ttUD01 THEN DO: /*Populate fields*/ assign ttUD01.Company = CUR-COMP ttUD01.Key1 = "AbcCode" /*Table that was affected*/ ttUD01.Key2 = "CountFreq" /*Field that was affected*/ ttUD01.Key3 = STRING(TIME,"HH:MM:SS") /*Time*/ ttUD01.Key4 = STRING(RECID(ttUD01)) /*To make the records unique*/ ttUD01.Date01 = TODAY /*Date*/ ttUD01.Number01 = ttAbcCode.CountFreq /*New Value*/ ttUD01.ShortChar01 = DCD-USERID. /*User id*/ /*Commit record*/ RUN UPDATE IN hUD01 ( {&input-output_dataset_UD01DataSet} ) NO-ERROR. END. /*IF available ttUD01*/ /*Clean up*/ delete object hUD01. END. /*IF VALID-HANDLE (hUD01)*/{&CATCH_PRIVATE}end procedure.

This example will use a business object to create a new row in UD01 when anABCCode entry is updated. Action File to BPM Custom Code.- PreProcessing directive on ABCCode Update method

C#:/* TO DO: replace DataSet variables with typed datasets. Add contract reference if necessary. */

var UD01DataSet = new System.Data.DataSet();var ttAbccode_xRow = (from ttAbccode_Row in ttAbccode select ttAbccode_Row).FirstOrDefault();hUD01 = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db);if (hUD01 != null){ hUD01.GETANEWUD01(UD01DataSet); var ttUD01_xRow = (from ttUD01_Row in ttUD01 where string.Equals(ttUD01_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) select ttUD01_Row).FirstOrDefault(); if (ttUD01_xRow != null) { ttUD01_xRow.Company = Session.CompanyID; ttUD01_xRow.Key1 = "AbcCode"; /*Table that was affected*/ ttUD01_xRow.Key2 = "CountFreq"; /*Field that was affected*/ ttUD01_xRow.Key3 = System.Convert.TimeToString(DateTime.Now, "HH:MM:SS"); /*Time*/ ttUD01_xRow.Key4 = ttUD01_xRow.SysRowID; /*To make the records unique*/ ttUD01_xRow["Date01"] = DateTime.Now; /*Date*/ ttUD01_xRow["Number01"] = ttAbccode_xRow.CountFreq; /*New Value*/ ttUD01_xRow["ShortChar01"] = Session.UserID; /*User id*/ /*Commit record*/ hUD01.UPDATE(UD01DataSet); }/*IF available ttUD01*/ /*Clean up*/ hUD01.Dispose();}

Page 9: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Exercise 3 – After CorrectionCorrected C#:/* TO DO: replace DataSet variables with typed datasets. Add contract reference if necessary. */

var UD01DataSet = new System.Data.DataSet();var ttAbccode_xRow = (from ttAbccode_Row in ttAbccode select ttAbccode_Row).FirstOrDefault();hUD01 = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db);if (hUD01 != null){ hUD01.GETANEWUD01(UD01DataSet); var ttUD01_xRow = (from ttUD01_Row in ttUD01 where string.Equals(ttUD01_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) select ttUD01_Row).FirstOrDefault(); if (ttUD01_xRow != null) { ttUD01_xRow.Company = Session.CompanyID; ttUD01_xRow.Key1 = "AbcCode"; /*Table that was affected*/ ttUD01_xRow.Key2 = "CountFreq"; /*Field that was affected*/ ttUD01_xRow.Key3 = System.Convert.TimeToString(DateTime.Now, "HH:MM:SS"); /*Time*/ ttUD01_xRow.Key4 = ttUD01_xRow.SysRowID; /*To make the records unique*/ ttUD01_xRow["Date01"] = DateTime.Now; /*Date*/ ttUD01_xRow["Number01"] = ttAbccode_xRow.CountFreq; /*New Value*/ ttUD01_xRow["ShortChar01"] = Session.UserID; /*User id*/ /*Commit record*/ hUD01.UPDATE(UD01DataSet); }/*IF available ttUD01*/ /*Clean up*/ hUD01.Dispose();}

Converted C#:/* TO DO: replace DataSet variables with typed datasets. Add contract reference if necessary. */

var UD01DataSet = new System.Data.DataSet();var ttAbccode_xRow = (from ttAbccode_Row in ttAbccode select ttAbccode_Row).FirstOrDefault();hUD01 = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db);if (hUD01 != null){ hUD01.GETANEWUD01(UD01DataSet); var ttUD01_xRow = (from ttUD01_Row in ttUD01 where string.Equals(ttUD01_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) select ttUD01_Row).FirstOrDefault(); if (ttUD01_xRow != null) { ttUD01_xRow.Company = Session.CompanyID; ttUD01_xRow.Key1 = "AbcCode"; /*Table that was affected*/ ttUD01_xRow.Key2 = "CountFreq"; /*Field that was affected*/ ttUD01_xRow.Key3 = System.Convert.TimeToString(DateTime.Now, "HH:MM:SS"); /*Time*/ ttUD01_xRow.Key4 = ttUD01_xRow.SysRowID; /*To make the records unique*/ ttUD01_xRow["Date01"] = DateTime.Now; /*Date*/ ttUD01_xRow["Number01"] = ttAbccode_xRow.CountFreq; /*New Value*/ ttUD01_xRow["ShortChar01"] = Session.UserID; /*User id*/ /*Commit record*/ hUD01.UPDATE(UD01DataSet); }/*IF available ttUD01*/ /*Clean up*/ hUD01.Dispose();}

Page 10: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Common Errors

Case SensitivityUse Of Unassigned Local Variable MessageE10 Equivalent to Row Mod = U or A

Page 11: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Case Sensitivity

For those who do not work with C# often, remember that it is case sensitive. For example, look at the below simple query:

var CustomerRecs = (from r in Db.customer from r_UD in Db.Customer_UD where r.SysRowID == r_UD.ForeignSysRowID && r.Company == Session.CompanyID && r.CustNum == ttOrderHedRow.CustNum select r_UD).FirstOrDefault();

This query will produce the following error message when you attempt to compile the BPM: Description: There is at least one compilation error. Details: Error CS1061: 'Erp.ErpContext' does not contain a definition for 'customer' and no extension method 'customer' accepting a first argument of type 'Erp.ErpContext' could be found (are you missing a using directive or an assembly reference?) Notice that the error message has customer with a lower case C? Change the following line Change the first line to an upper case C as below and the BPM compiles without error.

var CustomerRecs = (from r in Db.Customer

Page 12: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Unassigned Local VariableThe compiler will give an error message referring to an Unassigned Local Variable when the BPM’s logic is such that a variable may never get set. The below example

Erp.Tables.Customer Customer;Erp.Tables.Customer_UD Customer_UD;foreach (var ttCustomer_Row in ttCustomer){using (var txscope = IceDataContext.CreateDefaultTransactionScope()){Customer = (from Customer_Row in Db.Customer.With(LockHint.UpdLock)where Customer_Row.Company == ttCustomer_Row.Company &&string.Compare(Customer_Row.CustID, ttCustomer_Row.CustID, true) == 0select Customer_Row).FirstOrDefault();if (Customer != null)Customer_UD = (from Customer_UD_Row in Db.Customer_UD.With(LockHint.UpdLock)where Customer.SysRowID == Customer_UD_Row.ForeignSysRowIDselect Customer_UD_Row).FirstOrDefault();Customer_UD.CheckBox01 = true;Customer.CreditLimit = 0;Customer.CreditHold = false;Db.Validate();txscope.Complete();}}will generate the following error upon compilationServer Side ExceptionThere is at least one compilation error.Exception caught in: Epicor.ServiceModelError Detail============Description: There is at least one compilation error

Details:Error CS0165: Use of unassigned local variable 'Customer_UD'Notice that in the above example, the Customer_UD variable is only set whenif (Customer != null)We can correct this error by changing the second line of the example toErp.Tables.Customer_UD Customer_UD = null;This change ensures that the variable will be set to something regardless of the if statement.

Page 13: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

E10 Equivalent to Row Mod = U or AIn many BPM’s the user wants to peform some action if the tt record is a new record or updated record. In 9.05 the RowMod = A or U was used.

In 10, the equivalent is below

foreach (var ttAPInvHed_iterator in (from ttAPInvHed_Row in ttAPInvHed

where (string.Equals(ttAPInvHed_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) || string.Equals(ttAPInvHed_Row.RowMod, IceRow.ROWSTATE_UPDATED, StringComparison.OrdinalIgnoreCase))

select ttAPInvHed_Row))

Page 14: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Common Progress Commands

FOR EACH (used to loop through a table)FOR FIRST (used to find the first record in a table which meets where clause)CAN-FIND (used to identify existence of record)RUN PERSISTENTLY (used to run business objects on the sever)EXCLUSIVE LOCK direct database updatesIssue an exception Show informational messageSend an email

Page 15: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

FOR EACH

Page 16: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

FOR FIRST

Page 17: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

RUN PERSISTENTLY

Get an example of this .p calling into ud01

- Client Side – uses adapter as before- Server Side – use Service Renderer

Page 18: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Raise an exception

Page 19: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Show in informational message – custom code

Use PublishInfoMessage

Page 20: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Send an email// EMAIL BEGIN var splitter = new[] { ';' }; var mailer = new Epicor.Customization.Bpm.Implementation.AsyncSmtpMailer(); var message = new System.Net.Mail.MailMessage(); var from = BPM_from; 17 Revision 3

message.From = new System.Net.Mail.MailAddress(from); var to = BPM_to; foreach (var address in to.Split(splitter, StringSplitOptions.RemoveEmptyEntries)) { message.To.Add(new System.Net.Mail.MailAddress(address)); } var cc = BPM_cc; foreach (var address in cc.Split(splitter, StringSplitOptions.RemoveEmptyEntries)) { message.CC.Add(new System.Net.Mail.MailAddress(address)); } var subject = BPM_subject; message.Subject = subject; var body = BPM_body; message.Body = body; mailer.Send(this.Db, message, this.CompanyID); //

Page 21: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Programming Guide

Accessible on code converter about pageHelpful hints and how-to info

Page 22: Abl to c Sharp Conversion User Group Presentation

© 2013 Epicor Software Corporation

Questions