IDO Development Guide: Infor 13560 Morris Road Suite 4100 Alpharetta, Georgia 30004-8508
IDO Development Guide: Infor 13560 Morris Road Suite 4100 Alpharetta, Georgia 30004-8508
IDO Development Guide: Infor 13560 Morris Road Suite 4100 Alpharetta, Georgia 30004-8508
Version 8.00
Infor
13560 Morris Road
Suite 4100
Alpharetta, Georgia 30004-8508
www.Infor.com
IDO Development Guide
Copyright © 2008 Infor. All rights reserved. The word and design marks set forth herein are trademarks and/or registered trademarks of Infor and/or
related affiliates and subsidiaries. All other trademarks listed herein are the property of their respective owners.
The IDO responses are implemented in classes that mirror the requests, with the
IDOResponseEnvelope at the top of the hierarchy.
As an example, the following steps are required to execute an IDO runtime Invoke call
using IDOProtocol classes:
1. Create a new IDORequestEnvelope instance.
2. Set the IDORequestEnvelope.SessionID property.
3. Create a new IDORequest instance.
4. Set the IDORequest.Type property = Invoke.
5. Create a new InvokeRequestData instance.
6. Set the InvokeRequestData.IDOName property.
7. Set the InvokeRequestData.MethodName property.
8. Add the parameters to the InvokeRequestData.Parameters collection.
9. Add the IDORequest to the IDORequestEnvelope.Requests collection.
10. Set the payload for the IDORequest using the IDORequest.SetPayload method.
11. Send your completed IDORequestEnvelope to the IDO runtime and receive the
IDOResponseEnvelope in return.
IDO Commands Interface
Whether you are writing code on the client side or in an IDO extension class, the framework
also provides wrapper methods through the IDO Commands interface, These wrappers
typically reduce IDO interactions to a single line of code.
However, a limitation of using the IDO Commands interface is that you can specify only one
IDO request per command, and receive one response per command. When using the
IDOProtocols classes instead, you can build one IDORequestEnvelope that includes
multiple requests, and then receive one response that includes information for all the
requests.
AppDB Class
The AppDB class, part of the Mongoose.IDO.DataAccess namespace, is available only
to extension classes. It provides direct access to the application database, plus access to
common framework features such as application messages and session variables. For
more information about this class, see “AppDB Class” on page 3-14.
LoadCollectionResponseData LoadCollection(
LoadCollectionRequestData requestData );
UpdateCollectionResponseData UpdateCollection(
UpdateCollectionRequestData requestData );
InvokeResponseData Invoke(
InvokeRequestData requestData );
string[] GetIDONames();
LoadCollectionResponseData LoadCollection(
string idoName,
string propertyList,
string filter,
string orderBy,
int recordCap );
LoadCollectionResponseData LoadCollection(
string idoName,
PropertyList propertyList,
string filter,
string orderBy,
int recordCap );
InvokeResponseData Invoke(
string idoName,
string methodName,
params object[] parameters );
}
Function LoadCollection( _
ByVal idoName As String, _
ByVal propertyList As PropertyList, _
ByVal filter As String, _
ByVal orderBy As String, _
ByVal recordCap As Integer) As LoadCollectionResponseData
Function LoadCollection( _
ByVal idoName As String, _
ByVal propertyList As String, _
ByVal filter As String, _
ByVal orderBy As String, _
ByVal recordCap As Integer) As LoadCollectionResponseData
End Interface
The syntax for using the IIDOCommands interface will be different in other contexts such
as a form script or a standalone client application.
GetPropertyInfo
Use GetPropertyInfo to retrieve a list of properties and their attributes for an IDO.
Properties
The following table describes the properties available on the LoadCollectionRequestData
class
GetPropertyInfo Example
Dim response As GetPropertyInfoResponseData
response = Me.Context.Commands.GetPropertyInfo("SLItems")
For Each idoProp As PropertyInfo in response.Properties
String propertyName = idoProp.Name
' etc
Next
LoadCollection
Queries are performed using the LoadCollection API and associated protocol classes.
LoadCollection requests can be constructed using the LoadCollectionRequestData IDO
protocol class.
Properties
The following table describes the properties available on the LoadCollectionRequestData
class.
request.IDOName = "SLItems"
request.PropertyList.SetProperties("Item, Description, QtyOnHand")
request.Filter = "Item LIKE N'AB%'"
request.OrderBy = "QtyOnHand"
request.RecordCap = 0
response = Me.Context.Commands.LoadCollection(request)
qty = 0
For row As Integer = 0 To response.Items.Count
qty = qty + response(row, "QtyOnHand").GetValue(Of Integer)()
Next
UpdateCollection
Updates (includes inserts, updates and deletes) are performed using the UpdateCollection
API and associated protocol classes. UpdateCollection requests can be constructed using
the UpdateCollectionRequestData IDO protocol class. The following table describes the
properties available on the UpdateCollectionRequestData class.
Properties
Property Data Type Description
IDOName System.String Identifies the IDO used to execute the
request.
CollectionID System.String An identifier associated with this
UpdateCollection request.
RefreshAfterUpdate System.Boolean A boolean value used to indicate if the
caller wants the response to contain
the updated items refreshed after they
were saved.
CustomInsert System.String These properties are used to specify
custom actions to use when saving
CustomUpdate items. Note: same as custom
CustomDelete INS/UPD/DEL in WinStudio.
LinkBy Mongoose.IDO.Protocol. Applies to inner nested
PropertyPair array UpdateCollection requests only and
specifies the relationship between a
parent and child IDO in terms of
property pairs. Use the SetLinkBy
method to set this property. Default:
empty.
Items Mongoose.IDO.Protocol. An instance of the IDOUpdateItems
IDOUpdateItems class that contains zero or more
IDOUpdateItem instances. The
IDOUpdateItem class contains the
update information for a single item.
request.IDOName = "SLCustomers"
request.RefreshAfterUpdate = True
newCust.Action = UpdateAction.Insert
newCust.ItemNumber = 1 ' used for error reporting
newCust.Properties.Add("CustNum", "C000100")
newCust.Properties.Add("Name", "Boxmart")
newCust.Properties.Add("CurrCode", "USD")
newCust.Properties.Add("BankCode", "BK1")
request.Items.Add(newCust)
response = Me.Context.Commands.UpdateCollection(request)
sCoNum = ThisForm.PrimaryIDOCollection.GetCurrentObjectProperty("CoNum")
End If
End Sub
Invoke
IDO methods (not including custom load methods) are called uting using the Invoke API
and associated protocol classes. Invoke requests can be constructed using the
InvokeRequestData IDO protocol class. The following table describes the properties
available on the InvokeRequestData class.
Properties
Property Data Type Description
IDOName System.String Identifies the IDO used to execute the
request.
MethodName System.String Identifies the IDO method to be executed.
Parameters Mongoose.IDO.Protocol. A collection containing instances of the
InvokeParameterList InvokeParameter class corresponding to
the IDO method parameters.
request.IDOName = "UserNames"
request.MethodName = "UserValidSp"
request.Parameters.Add("ajones") ' user name, input
request.Parameters.Add(IDONull.Value) ' user ID, output
request.Parameters.Add(IDONull.Value) ' description, output
request.Parameters.Add(IDONull.Value) ' infobar, output
response = Me.Context.Commands.Invoke(request)
If response.IsReturnValueStdError Then
' get infobar output parameter
Dim errorMsg As String
errorMsg = response.Parameters(3).Value
Else
Dim userID As Integer
Dim desc As String
In many cases it will be more convenient to call the overloaded version of the Invoke
method that accepts parameters for the IDOName, MethodName and method parameters
InvokeRequestData properties.
Invoke Example 2
Dim response As InvokeResponseData
response = Me.Context.Commands.Invoke( _
"UserNames", _
"UserValid", _
"ajones", _
IDONull.Value, _
IDONull.Value, _
IDONull.Value)
If response.IsReturnValueStdError Then
' get infobar output parameter
Dim errorMsg As String
errorMsg = response.Parameters(3).Value
Else
Dim userID As Integer
Dim desc As String
Translation/Localization Considerations
All data values in IDO requests and responses are stored as string values in an "internal"
format that is independent of any regional settings for the application or local machine
where the code is executing.
Internal Format for Numbers
Numeric values are always stored internally using a period for the decimal separator (for
non-integer values) and without any digit-grouping characters.
Internal Format for Dates
Date values are always stored internally using the format YYYYMMDD HH:MM:SS.mmm
for date and time, YYMMDD for date only, and HH:MM:SS.mmm for time only (milliseconds
are optional).
Type Conversions
The IDO protocol classes store all property and parameter values internally as strings in a
non-localized internal format. However, the framework also provides methods that allow
you to transparently convert between supported native .NET CLR data types and the
internal formatted string values. You should always use strongly typed variables when
getting values from, or putting values into, any of the IDO protocol classes in order to take
advantage of this feature and avoid problems related to systems running with different
regional settings. This is especially important when working with date and numeric values.
The built-in VB functions for data type conversions (CStr, CDate, CInt, etc.) are sensitive
to the regional settings for the application or local machine.
Setting Property and Parameter Values
Use the SetValue or Add methods to set parameter and property values into the IDO
protocol classes.
Add/SetValue with InvokeRequestData
The following example shows how to do this with the InvokeRequestData IDO protocol
class.
Dim invokeRequest As New InvokeRequestData
Dim version As Integer = 600
Dim recordDate As DateTime = DateTime.Now
invokeRequest.IDOName = "MyIDO"
invokeRequest.MethodName = "MyMethod"
invokeRequest.Parameters.Add("Mongoose")
invokeRequest.Parameters.Add(version)
invokeRequest.Parameters.Add(Guid.NewGuid())
invokeRequest.Parameters.Add(recordDate)
invokeRequest.Parameters.Add(IDONull.Value) ' set later
Both the Add and SetValue methods accept a value of any supported .NET data type and
automatically handle the conversion to internal format, so that the developer does not need
to think about conversion issues.
updateItem.Action = UpdateAction.Insert
updateItem.Properties.Add("UserId", IDONull.Value) ' set later
updateItem.Properties.Add("UserName", "MGUser")
updateItem.Properties.Add("RecordDate", DateTime.Now)
updateItem.Properties.Add("RowPointer", Guid.NewGuid())
updateItem.Properties("UserId").SetValue(100L)
updateRequest.IDOName = "MyIDO"
updateRequest.Items.Add(updateItem)
loadResponse = Me.Context.Commands.LoadCollection( _
"UserNames", _
"UserId, UserName, RecordDate, RowPointer", _
"", "", 0)
loadResponse = Me.Context.Commands.LoadCollection( _
"UserNames", _
"UserId, UserName, RecordDate, RowPointer", _
"", "", 0)
filter = String.Format( _
"SessionId = {0} AND trans_num = {1}", _
SqlLiteral.Format(SessionID), _
SqlLiteral.Format(TransNum))
The above example will produce a filter with the appropriate syntax for the literal values,
similar to this:
SessionId = N' 7A4930D6-AE9E-4F32-9687-17ABDBF4E818' and trans_num =
1234
You must always pass in a strongly typed value in order to get the correct result. For
example, you should not pass a string containing a date value.
The following table shows some examples of input types, values, and the
SqlLiteral.Format result for each.
Transactions
The IDO runtime automatically executes all UpdateCollection requests in a transaction. It
also executes IDO methods in a transaction if they are marked as "transactional" methods.
All other IDO requests are executed without a transaction. Note that if a method is not
marked "transactional" is called from a method that is marked "transactional", then it will
still execute in the caller's transaction.
For transactional IDO methods, if the method returns an integer value less than 5, the
transaction will be committed. The exception is if the method was executed within an
existing outer transaction. Then the transaction will commit if and when the outer
transaction commits. If the IDO method returns an integer value greater than or equal to 5
the transaction will be rolled back immediately. The Infor ERP SL standard is to return 16
to indicate a method failed. The transaction will also roll back if the method throws an
exception.
If you need finer grained control over transaction scope, which is often necessary for long
running processes, this can be achieved while still allowing the IDO runtime to manage
transactions.
For example, consider a method that will post a large batch of records. We need a method
that will read the batch, loop through each record and attempt to post it. If the post is
successful the action should commit, otherwise it should be rolled back. The best way to
accomplish this is to create two methods: a top level entry point method that will query the
records to be posted, and another method to do the posting. The top level method should
not be marked as transactional, while the posting will be transactional. The entry point
method will query the records to be posted and loop through each one calling the posting
method to post each record. This way if a record fails to post it will not roll back all posted
records, only the failed record.
Parameters
• messageSource - A short, user-defined identifier of the source of a message (for
example, class or project name).
• messageType - One of the UserDefinedMessageType enumeration values; used for
searching and filtering log messages.
• message - A string containing the log message text.
• format - A log message format string (see String.Format() in the .NET Framework
documentation for more information about formatting strings).
• args - A variable-length list of format-string substitution parameters
Examples
IDORuntime.LogUserMessage( _
"SLCustomers", _
UserDefinedMessageType.UserDefined0, _
"Method A() called.")
IDORuntime.LogUserMessage( _
"SLCustomers", _
UserDefinedMessageType.UserDefined0, _
"Parameter 1 is {0}.", _
p1)
Wire Tap
You can use the Wire Tap feature of the IDO Runtime Development Server to monitor all
the IDO request and response documents generated by a specific user session. For more
information see the online help for the IDO Runtime Development Server.
Using client
' substitute a valid SL user, password and configuration name
response = client.OpenSession("user", "password", "config")
If response.LogonSucceeded Then
Console.WriteLine("Success")
End If
Close Session
The CloseSession method is used to close an existing session (log out).
The OpenSession example above also includes an example of CloseSession.
GetConfigurations
WinStudio/SL configuration information is stored in MongooseConfigs.xml. By default,
this file is created and resides in c:\Documents and Settings\All Users\Application
Data\Mongoose.
The Client class accesses configuration information through the ConfigServer.aspx page
(IDORequestService ASP.NET Web server application) in conjunction with the IDO
Runtime Service or the IDORuntimeHost.exe developer tool. The Web Server application,
IDO Runtime Service and IDORuntimeHost.exe are all installed as part of a Infor ERP SL
utility server install. Configuration information obtained via the GetConfigurations static
method includes a subset of configuration properties and all of the referenced application
properties.
In code that utilizes the Client class, include the following using statements (Import
statements if written in a VB project):
using Mongoose.Core.Configuration;
using Mongoose.IDO.Protocol;
using Mongoose.IDO;
ConfigurationInfo Example 1
The following snippet of code retrieves an array of ConfigurationInfo classes through the
IDORequestService. (Infor IDO Runtime Service must be running for this method to work.)
//********************************************************************
// The following line calls the IDORequestClient ASPX web application
// to retrieve the configuration list via an array of ConfigurationInfo
// classes.
// Parm -> URL to IDORequestClient's ConfigServer.apsx file.
//********************************************************************
ConfigurationInfoList configList = null;
configList = Client.GetConfigurations(
@"http://server1/
IDORequestService/ConfigServer.aspx", "Acme" );
// Config info can be enumerated as follows
foreach ( ConfigurationInfo config in configList )
{
// do whatever
}
ConfigurationInfo Example 2
The following snippet of code retrieves an array of ConfigurationInfo classes through
IDORuntimeHost.exe. (IDORuntimeHost.exe must be running for this method to work.)
//********************************************************************
// The following line calls through to the local IDO runtime service
// (IPC protocol) to retrieve the configuration list via an array of
// ConfigurationInfo classes.
// Note: No parameter is passed to the GetConfigurations() method.
//********************************************************************
ConfigurationInfoList configList = null;
configList = Client.GetConfigurations();
Properties
The following configuration/application properties are available through the
ConfigurationInfo class.
Example
The following snippet of code retrieves an array of configuration names, gets the
application name and a couple of application properties, and finally retrieves the Runtime
Forms Database name (encrypted.)
// Create instance of ManageConfigs class
MongooseConfigs ManageConfigs = null;
ManageConfigs = new MongooseConfigs();
// Load MongooseConfigs.xml
ManageConfigs.Load(true);
// Get array of the configuration names
string[] configNames = ManageConfigs.GetConfigNames();
foreach ( string configName in configNames )
{
// Get config info
Configuration config = ManageConfigs.GetConfig( configName );
// Get Application info
AppProperties appInfo = ManageConfigs.GetAppProperties(
config.Application );
// Get Connection Info (most properties here are encrypted)
ConnectionProfile connProfile = ManageConfigs.GetFormsConnection(
configName,
ConnectionProfileType.Runtime );
// Note: Various information can be retrieved from the Configuration,
AppProperties, and
// ConnectionProfile classes. You can view the availabe class
properties via intellisense
// when programming against them.
}
Properties
The following configuration/application properties are available through the Configuration
class:
public string Application;
public string ConfigName;
public ArrayList ConnectionRoles;
public bool FormControlSSEnabled;
public string ObjectStudioProjBuildDir;
public bool ObjectStudioSSEnabled;
public string SSPassword; (encrypted string)
public string SSProjectName;
public string SSUNCPath;
public string SSUserId; (encrypted string)
IDOCore.dll
IDOProtocol.dll
MGShared.dll
7. On the Project menu, select Add New Item.
8. Select Code File, name the new file AssemblyInfo.vb, and click OK.
9. Open the new AssemblyInfo.vb source file and add this assembly attribute:
<Assembly: Mongoose.IDO.IDOExtensionClassAssembly("assembly-name")>
Substitute a meaningful name for the assembly-name parameter. This can be anything
but typically is the name of the IDO project associated with the classes in this assembly.
When this class library is imported the IDO Custom Assemblies form, the name you
specify here becomes the name of the assembly.
Importing Assemblies
Use the IDO Custom Assemblies form in Infor ERP SL to import assemblies.
Link the IDO to the custom assembly on the IDOs form by checking out the IDO and
entering the Custom Assembly Name (the Assembly Name from the IDO Custom
Assemblies form), the Ext Class Name (the name of the class - usually the same as the
IDO), and the Ext Class Namespace (usually the same as the Project Name).
Link the methods in the extension class to the IDO by entering the Method Name and
specifying the Parameters list on the IDO Methods form. The Method Type will be
Handcoded - Standard Method or Handcoded - Custom Load Method.
Mongoose.IDO.IIDOExtensionClassContext Interface
The SetContext method is called once when the extension class is created, passing a
reference to the IIDOExtensionClassContext interface for accessing the calling user's
context.
Public Interface IIDOExtensionClassContext
ReadOnly Property IDO() As Mongoose.IDO.IVirtualIDO
ReadOnly Property Commands() As Mongoose.IDO.IIDOCommandHelper
End Interface
End Class
It is generally a good idea to import some common framework namespaces to make your
code less verbose and clearer, and to enable the Explicit and Strict VB compiler options.
IDO Extension Class Starter Template
The following sample code may be used as a template for creating new IDO extension
classes.
Option Explicit On
Option Strict On
Imports Mongoose.IDO
Imports Mongoose.IDO.Protocol
Imports Mongoose.IDO.DataAccess
Imports Mongoose.Core.Common
<IDOExtensionClass("class-name")> _
Public Class class-name
Inherits ExtensionClassBase
End Class
Adding Methods
In order to call a method on an IDO extension class, the method must be declared as public
and it must also be defined in the IDO metadata as a hand-coded method. This is different
from previous versions of the framework, where the metadata for a method was defined by
convention, using the Do not generate source attribute, but not required.
A hand-coded method may be either a standard method, which is a Function with zero or
more input/output parameters and returns an integer, or a custom load method, which is a
Function with zero or more parameters and returns an instance of either an IDataReader
or a DataTable (see the .NET Framework documentation for information about these).
When implementing a hand-coded method that will be callable through the IDO runtime,
you could add the optional IDOMethod attribute, which may be used in the future to
facilitate adding the necessary IDO metadata to make the method accessible.
Sample Standard Method Call
For example, the declaration of a standard method might look like the following Function
declaration:
<IDOMethod(MethodFlags.None, "Infobar")> _
Public Function DoWork( _
ByVal SessionID As String, _
ByVal TransNum As Long, _
ByRef Infobar As String) As Integer
End Function
IDOMethod Parameters
The IDOMethod attribute takes two optional parameters: flags and messageParm.
Flags
The flags parameter is one or more of the values defined by the MethodFlags
enumeration. This table shows the MethodFlags values:
MessageParm
The messageParm parameter is a string and is the name of the parameter that will be used
to return messages to the caller (Infobar). The parameter that is identified should be
declared as a String and passed ByRef.
Remember that these attributes are not used at run time. They may be used in the future
to facilitate adding and synchronizing the IDO metadata for an extension class and its
methods when an assembly is imported.
Event Description
PreLoadCollection Fires when a LoadCollection request is received.
PostLoadCollection Fires after a LoadCollection request has been processed.
PreUpdateCollection Fires when an UpdateCollection request is received.
PostUpdateCollection Fires after an UpdateCollection request has been processed.
These IDO events are available on the IDO property of the IIDOExtensionClassContext
interface. To add your handler to an IDO event you must override the
ExtensionClassBase.SetContext method in your IDO extension class and use the
AddHandler keyword as shown in the following example.
Public Overrides Sub SetContext( _
ByVal context As IIDOExtensionClassContext)
End Sub
The following table describes the contents of the IDOEventArgs parameter for each IDO
event.
An event handler method can access the IDO request and response payloads as shown in
the following examples.
Private Sub HandlePreLoadCollection( _
ByVal sender As Object, _
ByVal args As IDOEventArgs)
loadRequest = CType(args.RequestPayload,
LoadCollectionRequestData)
' ...additional logic based on loadRequest...
End Sub
loadRequest = CType(args.RequestPayload,
LoadCollectionRequestData)
loadResponse = CType(args.ResponsePayload,
LoadCollectionResponseData)
' ...additional logic based on loadRequest or loadResponse...
End Sub
updateRequest = CType(args.RequestPayload,
UpdateCollectionRequestData)
' ...additional logic based on updateRequest...
End Sub
updateRequest = CType(args.RequestPayload,
UpdateCollectionRequestData)
updateResponse = CType(args.ResponsePayload,
UpdateCollectionResponseData)
' ...additional logic based on loadRequest or loadResponse...
End Sub
End Sub
The ActionMask is usually a combination of Insert, Update and Delete (All), meaning the
UpdateCollection that was just performed executed all types of actions.
However, there are certain circumstances when this may be a subset of Insert, Update and
Delete, which means only the items that match the mask were actually saved. There are
times when the IDO runtime must save items in a particular order (with nested updates),
and it may first process only deleted items; then in another pass it will execute all inserts
and updates.
ActionMask is valid for both Pre- and PostUpdateCollection. The PreUpdateCollection
parameters are the same as the PostUpdateCollection parameters – but the action
indicates which items are about to be saved, rather than which items were just saved.
Replacing Standard IDO Processing with Event Handlers
By adding event handlers, not only can you perform additional logic when a particular event
fires, but in the case of PreUpdateCollection and PreLoadCollection you can also
completely replace the default framework implementation by constructing your own
response and setting that in the IDOEventArgs.ResponsePayload field. The following
example shows how this is done for an UpdateCollection request.
Private Sub HandlePreUpdateCollection( _
ByVal sender As Object, _
ByVal args As IDOEventArgs)
updateRequest = CType(args.RequestPayload,
UpdateCollectionRequestData)
End Sub
Properties
Property Description
eventName The name of the event to generate
synchronous Determines if the event handlers should be executed
synchronously (True) or asynchronously (False).
transactional Determines if the event handlers should be executed in a
transaction. If passed as False and one of the synchronous
handlers fails, any database activity performed by prior
handlers will remain committed.
result The value of the last RESULT() keyword executed on a Finish
or Fail action on any handler.
parameters An array of named parameters passed to the event handlers.
Example
Option Explicit On
Option Strict On
Imports Mongoose.IDO
Imports Mongoose.IDO.Protocol
Imports Mongoose.IDO.DataAccess
Imports Mongoose.Core.Common
<IDOExtensionClass("MyIDO")> _
Public Class TestFiringEvent
Inherits ExtensionClassBase
<IDOMethod(MethodFlags.None, "Infobar")> _
Public Function FireMyEvent( _
ByVal Parm1 As String, _
ByVal Parm2 As Long, _
ByRef Infobar As String) As Integer
End Function
End Class
Code Samples
The examples in this section assume you are writing code in an IDO extension
class that inherits from the Mongoose.IDO.ExtensionClassBase class.
LoadCollection Examples
The following sample code demonstrates executing a LoadCollection for the
SLTtJobtMatPosts IDO, bringing back the TransNum and TransSeq properties.
Dim loadResponse As LoadCollectionResponseData
loadResponse = Me.Context.Commands.LoadCollection( _
"SLTtJobtMatPosts", _
"TransNum,TransSeq", _
filter, String.Empty, 0)
The following sample demonstrates executing a LoadCollection for the IDO that the
extension class belongs to (the current instance of the executing IDO).
Dim loadResponse As LoadCollectionResponseData
loadResponse = Me.LoadCollection( _
"TransNum, EmpNum, EmpEmpType, EmpDept, DerJobPWcDept ", _
filter, _
"Posted, LowLevel DESC, Job, Suffix, CloseJob, TransNum", _
0)
UpdateCollection Examples
Inserting a New Item
The following sample demonstrates inserting a new item.
Dim request As New UpdateCollectionRequestData
Dim response As New UpdateCollectionResponseData
Dim customerItem As New IDOUpdateItem
request.IDOName = "SLCustomers"
request.RefreshAfterUpdate = True
customerItem.Action = UpdateAction.Insert
customerItem.Properties.Add("CoNum", "C000100")
customerItem.Properties.Add("Name", "New Company")
customerItem.Properties.Add("CreditHold", 1I)
request.Items.Add(customerItem)
response = Me.Context.Commands.UpdateCollection(request)
loadResponse = Me.Context.Commands.LoadCollection( _
"SLCustomers", _
"CoNum, Name, CreditHold", _
"CoNum = N'C000100'", _
"", _
1)
If loadResponse.Items.Count = 1 Then
request.IDOName = "SLCustomers"
request.RefreshAfterUpdate = True
request.Items.Add(customerItem)
response = Me.Context.Commands.UpdateCollection(request)
End If
Invoke Example
The following sample demonstrates invoking the JobtClsLogErrorSp method on the
SLJobtCls IDO, passing two parameters and retrieving the output value for the second
parameter.
Dim invokeResponse As New InvokeResponseData
Dim message As String
invokeResponse = Me.Context.Commands.Invoke( _
"SLJobtCls", _
"JobtClsLogErrorSp", _
TransNum, IDONull.Value)
message = invokeResponse.Parameters(1).Value
AppDB Class
The AppDB class, part of the Mongoose.IDO.DataAccess namespace, provides direct
access to the application database, plus access to common framework features such as
application messages and session variables. You may create a new instance of this class
by calling the CreateAppDB method, which is implemented by the ExtensionClassBase
class.
Application Database Connections
In general, the best practice for accessing the database to execute queries, updates or
stored procedure calls is to go through the Infor framework using IDO requests. However,
there may be times when it is necessary or more efficient to access the database directly
(for example, building and executing dynamic SQL or iterating through records from an
extremely large query result set). Direct database access is accomplished using the
standard .NET Framework SQL Server classes: SqlConnection and SqlCommand. See
the Microsoft .NET Framework documentation for more information on these classes.
Opening a Connection to the Application SQL Server Database
The AppDB.Connection property provides an opened SqlConnection instance pointing
to the application database. By going through the AppDB.Connection property, the
framework is able to open and initialize the connection based on the calling user's session
information.
Executing SQL Server Commands
The SqlCommand class is used to execute stored procedures, queries, updates, or any
other T-SQL command. The SqlCommand may be created by using the VB New operator
and setting the necessary properties on the command, as described in the .NET
Framework documentation. However, when the command is executed, you should use the
AppDB.ExecuteScalar, AppDB.ExecuteNonQuery, or AppDB.ExecuteReader
methods. This allows you to leverage the framework infrastructure for executing SQL
commands including logging and exception-message translation.
Application Messages
Access to translatable strings and messages stored in the application database message
tables is implemented by the AppDB class. The strings and messages that are returned
are queried and constructed according to the calling session's regional settings. Access is
provided through the IMessageProvider interface and makes use of application database
messaging stored procedures such as MsgAppSp.
The following methods are published by the IMessageProvider interface:
Method Description
Public Function GetMessage( _ Get a string or message by message ID.
msgID As String ) As String
Public Function GetMessage( _ Get a string or message by message ID
msgID As String, _ with substitution parameters.
ParamArray args() As Object ) _
As String
Public Function AppendMessage( _ Append a string or message by message
message As String, _ ID.
msgID As String ) As String
Public Function AppendMessage ( _ Append a string or message by message
message As String, _ ID with substitution parameters.
msgID As String, _
ParamArray args() As Object ) _
As String
Method Description
Public Function GetErrorMessage( _ Get a constraint error message by object
objectName As String, _ name and type.
messageType As AppMessageType ) _
As String
Public Function GetErrorMessage( _ Get a constraint error message by object
objectName As String, _ name and type with substitution
messageType As AppMessageType, _ parameters.
ParamArray args() As Object ) _
As String
Infobar = messageProvider.AppendMessage( _
Infobar, _
"I=CmdMustPerform", _
"@:PostPendingMaterialTransactions")
End Using
If you are writing code in an extension class method for a class that derives from
ExtensionClassBase, you can simply call the
ExtensionClassBase.GetMessageProvider method as a shortcut to getting a reference
to the IMessageProvider interface, as shown in this example:
Dim messageProvider As IMessageProvider = Nothing
messageProvider = Me.GetMessageProvider()
Session Variables
The AppDB class publishes the following methods for manipulating session variables for
the caller's session.
Method Description
Public Sub SetSessionVariable( _ Set the value of a session variable.
ByVal name As String, _
ByVal varValue As String )
Public Function GetSessionVariable( _ Get the value of a session variable.
ByVal name As String ) As String
Public Function GetSessionVariable( _ Get the value of a session variable,
ByVal name As String, _ returning the specified default value if it
ByVal defaultValue As String ) _ does not exist.
As String
Public Function GetSessionVariable( _ Get the value of a session variable,
ByVal name As String, _ returning the specified default value if it
ByVal defaultValue As String, _ does not exist, and delete it if it does exist.
ByVal delete As Boolean ) As String
Public Sub DeleteSessionVariable( _ Delete a session variable.
ByVal name As String )
End Function
Note that the AppDB instance is created as part of the Using…End Using block. This
ensures that the AppDB instance will be disposed and any resources it is holding will be
released as soon as the instance goes out of scope. See the .NET Framework
documentation for more information on the Using statement.
See the .NET Framework documentation for more information on the IDisposable
interface.
Translation/Localization Considerations
Type Conversions
The built-in VB functions for data type conversions (CStr, CDate, CInt, etc.) are sensitive
to the regional settings for the application or local machine, and therefore should not be
used for type conversions in IDO extension class methods.
The framework stores all property values internally as strings regardless of their data type.
In WinStudio, this is also true for values stored in components, variables and IDO
collections. The internal string format is culture independent so the built-in string
conversion functions may not work, or may work inconsistently depending on the data or
the current culture settings. The internal formatted string value is always available, but
when accessing numeric, date or Guid property values programmatically, you should use
the APIs provided by the framework that will convert the values from internal string format
to the proper “strong” data types.
IDORequest/Response Property Values (IDOProtocol classes)
Property values in IDO Request and Response classes are represented using the
Mongoose.IDO.Protocol.IDOValueType class, or a class that inherits from this class.
The following example accesses properties in a LoadCollectionResponseData instance:
Dim responseData As LoadCollectionResponseData
Dim name As String
Dim recordDate As DateTime
Dim cost As Decimal
Dim newCost As Decimal = 100.00
Dim id As Guid
'…perform LoadCollection…
Note that the name property simply gets the internal format, since string values do not need
conversion. Also note that the GetValue call for the cost property specifies an optional
default value to return if the property is null. You can also check for null values using the
IsNull property.
The last line assigns a new value to the cost property. Passing in a decimal value to the
SetValue method allows the framework to perform the conversion to the internal string
format automatically.
Converting Internal Format Strings to Strong Typed Variables
WinStudio supports a similar set of methods for automatically converting internal format
strings to strong typed variables in scripts, as shown in the following example.
Dim name As String
Dim recordDate As DateTime
Dim cost As Decimal
Dim newCost As Decimal = 100.00
Dim id As Guid
ThisForm.PrimaryIDOCollection(0).Properties("Cost").SetValue(newCost)
Note that there are individual methods for each data type, instead of a single generic
method that is supported in the IDOProtocol classes. Also, the methods all require a
default value to return if the requested value is null.
Again, the last line assigns a new value to the cost property. Passing in a decimal value to
the SetValue method allows the framework to perform the conversion to the internal string
format automatically
You should now be able to set breakpoints in the Visual Studio 2005 debugger and step
through code.
Logging Diagnostic Messages
IDO extension class methods can send messages to the common logging facility IDO
Runtime Development Server (IDORuntimeHost.exe) by calling one of the overloaded
IDORuntime.LogUserMessage methods. For more information about the facility, see
“Diagnostics and Debugging” on page 2-19.
Example
This sample sends a message to the log each time the ValidateCreditCard method is
called.
• The first parameter is messageSource (String). This is the source identifier that will
display in the log viewer.
• The second parameter is messageType (Mongose.IDO.UserDefinedMessageType).
This is the type identifier that will display in the log viewer.
• The third parameter is message (String). This is the text of the message to be logged.
<IDOMethod(MethodFlags.None, "infobar")> _
Public Function ValidateCreditCard( _
ByVal cardNumber As String, _
ByVal expires As DateTime, _
ByVal amount As Decimal, _
ByVal infobar As String) As Integer
Return result
End Function