WM-Synergy Business Objects
WM-Synergy Business Objects, SBO, is a comprehensive transaction library built on the both the .net standard and .net framework platforms. This library allows the developer to quickly read/write/update transactional data with the Visual ERP database.
- Ensures that all tables required for a data transaction are properly updated.
- Synergy supports this product, if you find a bug, we will fix it at no cost to you.
- The code base allows you as a developer to write your own SQL code as needed.
- The code allows for roll back of transactions if a record does not complete properly.
As an end user you must apply your licensee code to be able to use WM-Synergy Business Objects.
If you are using https:\\ to the authenticator, make sure the certificate on the site is valid.
Otherwise you might see something similar to the following:

For customers that purchased SBO a license manager server is installed. This is a local installation running in IIS
AuthenticationServer on port 8089 - it is a webservice that evaluates the domain against the license key. During the initial database connection (passing in the URL from the implemented application) the webservice is called and evaluated
The SBO installer package comes with sample programs on how to use the SynergyBusinessObjects.dll library see your installed Examples subfolder.
As Microsoft moves away from standard system libraries included with Windows, it becomes important to include in your developer project any and all libraries that are provided with this SDK kit.
With updates for support of Visual 11 the SynergyBusinessObjects.dll relies on Oracle.ManagedDataAccess.dll, even if you are a Microsoft SQL only facility.
The following libraries may also be required, in a customer created project: the version may not matter if your project is a .exe you should be able to use the latest from nuget.
- Microsoft.Data.SqlClient.dll
- Oracle.ManagedDataAccess.dll (min 21.18.0)
- System.Configuration.ConfigurationManager (min 6.0.1)
- <-- might be needed. -->
- Azure.Core (min 1.38.0)
- Azure.Identity (min 1.11.4)
- Microsoft.CSharp
- Microsoft.Identity.Client (min 4.6.1.3)
- Microsoft.BclAsyncInterfaces (min 9.0.3)
- Microsoft.Data.SqlClient.SNI (min 5.2.0)
- Microsoft.Identity.Client (min 4.61.3)
- Microsoft.Identity.Client.Extensions.Msal (min 4.61.3)
- Microsoft.IdentityModel.JsonWebTokens (min 6.35.0)
- Microsoft.IdentityModel.Abstractions (min 6.35.0)
- Microsoft.IdentityModel.JsonWebTokens(min 6.35.0)
- Microsoft.IdentityModel.Logging (min 6.35.0)
- Microsoft.IdentityModel.Protcols (min 6.35.0)
- Microsoft.IdentityModel.Protcols.OpenIdConnection (v6.35.0)
- Microsoft.IdentityModel.Tokens (min 6.35.0)
- System.Buffers.dll min (4.6.1)
- System.ClientModel (min 1.0.0)
- System.Diagnostics.DiagnosticSource (min 6.0.1)
- System.Diagnostics.PerformanceCounter(min 6.0.2)
- System.DirectoryServices.Protocols(min 6.0.2)
- System.formats.Asn1.dll (min 9.0.3)
- System.IdentityModel.Tokens.Jwt (min 6.35.0)
- System.IO.FileSystem.AccessControl (min 5.0.0)
- System.IO.Pipelines.dll ( v9.0.3)
- System.Memory.dll (min 4.6.2)
- System.Memory.Data (min 1.0.2)
- System.Net.Http (min 4.3.4)
- System.Numerics.Vectors.dll (min 4.6.1)
- System.Runtime.InteropServices.Unsafe (min 6.1.1)
- System.Runtime.InteropServices.RuntimeInformation(min 4.3.0)
- System.Security.AccessControls (min 6.0.0)
- System.Security.Cryptography.Algorithms (min 4.3.0)
- System.Security.Cryptography.Encoding(min 4.3.0)
- System.Security.Cryptography.Primitives (min 4.3.0)
- System.Security.Cryptography.ProtectedData (min 4.7.0)
- System.Security.Cryptography.X509Certificates (min 4.3.0)
- System.Security.Permissions (min 6.0.0)
- System.Security.Principal.Windows (min 5.0.0)
- System.Text.Encoding (min 4.3.0)
- Sytem.Text.Encodings.Web.dll (min 9.0.3)
- System.Text.Json.dll (min9.0.3)
- System.Threading.Tasks.Extensions.dll (min4.6.2)
- System.Value.Tuple.dll (min 4.6.1)
For .net standard make sure to include:
- Oracle.ManagedDataAccess (nuget)
- Microsoft.Data.SqlClient (nuget Use the correct version for your build)
- System.Configuration.ConfigurationManager (min 6.0.1)
- <<< might be needed as well >>>
- System.Net.Http
- System.ServiceModel
- System.ServiceModel.Duplex
- System.ServiceModel.Http
- System.ServiceModel.NetTcp
- System.ServiceModel.Primitives
- System.ServiceModel.Security
Please note, the .net framework version of sbo objects will be retired as .net standard will replace it.
Starting with Visual 11 support for single site, Visual ERP 7 and below, is no longer supported or provided with sbo objects.
We can provide a non-supported version SynergyBusinessObjects70.dll (available upon request).
Connection Test
- [TestClass]
- public class ConnectionTest
- {
- #region Private Methods
- /// <summary>
- /// <c>GetSBOAuthenticator</c> url as specified in the app.config.
- /// </summary>
- /// <returns></returns>
- private Uri GetSBOAuthenticator()
- {
- Uri Url = null;
- SBOServer.AuthenticationService Svc = new SBOServer.AuthenticationService();
- ConfigurationManager.AppSettings["SchemaPath"] = Environment.CurrentDirectory + "\\";
- string SBOServer = ConfigurationManager.AppSettings["SBOServer"].ToString();
- string SBOPort = ConfigurationManager.AppSettings["SBOPort"].ToString();
- Url = new Uri(string.Format("http://{0}:{1}/AuthenticationService.asmx", SBOServer, SBOPort));
- return Url;
- }
- /// <summary>
- /// <c>ConnectToDbase</c> using the values set in the App.config file.
- /// </summary>
- /// <returns>Database connection</returns>
- private Synergy.BusinessObjects.DatabaseConnection ConnectToDbase()
- {
- Uri Url = GetSBOAuthenticator();
- Synergy.BusinessObjects.DatabaseConnection DataBase = new Synergy.BusinessObjects.DatabaseConnection(Url);
- //Connection information
- string DBType = ConfigurationManager.AppSettings["DBType"].ToString();
- string DBServer = ConfigurationManager.AppSettings["DBServer"].ToString();
- string DBDatabase = ConfigurationManager.AppSettings["DBDatabase"].ToString();
- string DBUser = ConfigurationManager.AppSettings["DBUserId"].ToString();
- string DBPassword = ConfigurationManager.AppSettings["DBPassword"].ToString();
- DataBase.UserCredentials.UseBlind = true; //Default Value = true
- DataBase.UserCredentials.DatabaseType = (DBType == "SqlServer" ? Synergy.BusinessObjects.DatabaseEngineType.SqlServer : Synergy.BusinessObjects.DatabaseEngineType.Oracle);
- DataBase.UserCredentials.Server = DBServer; //Enter the Server (and instance name for SqlsErver)
- DataBase.UserCredentials.Database = DBDatabase;
- DataBase.UserCredentials.UserID = DBUser;
- DataBase.UserCredentials.Password = DBPassword;
- DataBase.Connect();
- return DataBase;
- }
- #endregion
- #region Unit Tests
- [TestMethod]
- public void AuthenticationTest()
- {
- Uri Url = null;
- SBOServer.AuthenticationService Svc = new SBOServer.AuthenticationService();
- try
- {
- Url = GetSBOAuthenticator();
- Svc.Url = Url.ToString();
- Svc.AuthenticateNode("Test");
- Svc.Dispose();
- Assert.AreEqual(1, 1); // Success
- }
- catch (Exception ex)
- {
- Assert.Fail(ex.Message);
- }
- }
- [TestMethod]
- public void ConnectToDatabase()
- {
- try
- {
- //Create the Database Connection – define the Connection Manager Server
- Synergy.BusinessObjects.DatabaseConnection Database = ConnectToDbase();
- if (Database.Connected)
- {
- Assert.IsTrue(1 == 1, "Database Connection is a Success!");
- Database.CloseConnection();
- }
- else
- Assert.Fail("Check the app.config settings.");
- }
- catch (Exception ex)
- {
- Assert.Fail(ex.Message);
- }
- }
- #endregion
- }
Connect To Database
- /// <summary>
- /// <c>ConnectToDbase</c> using the values set in the App.config file.
- /// </summary>
- /// <returns>Database connection</returns>
- private Synergy.BusinessObjects.DatabaseConnection ConnectToDbase()
- {
- Uri Url = GetSBOAuthenticator();
- Synergy.BusinessObjects.DatabaseConnection DataBase = new Synergy.BusinessObjects.DatabaseConnection(Url);
- //Connection information
- string DBType = ConfigurationManager.AppSettings["DBType"].ToString();
- string DBServer = ConfigurationManager.AppSettings["DBServer"].ToString();
- string DBDatabase = ConfigurationManager.AppSettings["DBDatabase"].ToString();
- string DBUser = ConfigurationManager.AppSettings["DBUserId"].ToString();
- string DBPassword = ConfigurationManager.AppSettings["DBPassword"].ToString();
- DataBase.UserCredentials.UseBlind = true; //Default Value = true
- DataBase.UserCredentials.DatabaseType = (DBType == "SqlServer" ? Synergy.BusinessObjects.DatabaseEngineType.SqlServer : Synergy.BusinessObjects.DatabaseEngineType.Oracle);
- DataBase.UserCredentials.Server = DBServer; //Enter the Server (and instance name for SqlsErver)
- DataBase.UserCredentials.Database = DBDatabase;
- DataBase.UserCredentials.UserID = DBUser;
- DataBase.UserCredentials.Password = DBPassword;
- DataBase.Connect();
- return DataBase;
- }
Code Example with SQL.INI
(See: Sample Programs/Starter MultiSite for detailed code usage in your sdk kit)
Incorporate the SQL INI code to your database connection.
- private static void ParseSqlIni(string database, ref AuthenticationCredentials authCreds)
- {
- SqlINIEntry sqlINIEntry = new SqlINI().ParseSqlIni(database);
- if (sqlINIEntry.HasWarning) throw (new Exception("'sql.ini' File error: " + sqlINIEntry.WarningMessage));
- if (sqlINIEntry.DatabaseType == DatabaseTypeEnum.SqlServer || sqlINIEntry.DatabaseType == DatabaseTypeEnum.Oracle)
- {
- if (sqlINIEntry.DatabaseType == DatabaseTypeEnum.SqlServer)
- authCreds.DatabaseType = DatabaseEngineType.SqlServer;
- else
- authCreds.DatabaseType = DatabaseEngineType.Oracle;
- authCreds.Server = sqlINIEntry.ServerName;
- authCreds.Database = sqlINIEntry.DatabaseName;
- }
- }
SqlINI.cs
- using System;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Text;
- namespace Synergy.INI
- {
- public class SqlINI
- {
- #region Externals
- internal static class NativeMethods
- {
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal static extern uint GetPrivateProfileString(
- string lpAppName,
- string lpKeyName,
- string lpDefault,
- StringBuilder lpReturnedString,
- uint nSize,
- string lpFileName);
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal static extern uint GetPrivateProfileSection(
- string lpAppName,
- IntPtr lpReturnedString,
- uint nSize,
- string lpFileName);
- }
- #endregion
- #region Enums
- public enum DatabaseTypeEnum
- {
- None,
- Oracle,
- SqlServer
- }
- #endregion
- #region SqlINIEntry class
- public class SqlINIEntry
- {
- public DatabaseTypeEnum DatabaseType = DatabaseTypeEnum.None;
- public string ServerName = string.Empty;
- public string DatabaseName = string.Empty;
- public string WarningMessage = string.Empty;
- public bool HasWarning
- {
- get
- {
- return !string.IsNullOrEmpty(WarningMessage);
- }
- }
- }
- #endregion
- #region Methods
- private static string[] GetPrivateProfileSection(string sectionName, string iniFileName)
- {
- string[] sectionKeyArray = null;
- if (!File.Exists(iniFileName)) return null;
- uint MAX_BUFFER = 32767;
- IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
- uint bytesReturned = NativeMethods.GetPrivateProfileSection(sectionName, pReturnedString, MAX_BUFFER, iniFileName);
- if ((bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))
- {
- Marshal.FreeCoTaskMem(pReturnedString);
- return null;
- }
- // bytesReturned -1 to remove trailing \0
- // NOTE: Calling Marshal.PtrToStringAuto(pReturnedString) will
- // result in only the first pair being returned
- string returnedString = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned - 1);
- sectionKeyArray = returnedString.Split('\0');
- Marshal.FreeCoTaskMem(pReturnedString);
- return sectionKeyArray;
- }
- private string INIRead(string sectionName, string sKeyName, string iniFileName)
- {
- StringBuilder sb = new StringBuilder(500);
- uint charCount = NativeMethods.GetPrivateProfileString(sectionName, sKeyName, string.Empty, sb, (uint)sb.Capacity, iniFileName);
- if (charCount > 0) return sb.ToString().Substring(0, (int)charCount);
- else return string.Empty;
- }
- public SqlINIEntry ParseSqlIni(string database)
- {
- SqlINIEntry sqlINIEntry = new SqlINIEntry();
- try
- {
- // sql.ini search order
- // current working dir i.e. the Visual program dir
- // %windir%\system32
- // %windir%\system
- // %windir%
- // %PATH% order
- string[] sysPaths = new string[4];
- sysPaths[0] = Path.Combine(Environment.CurrentDirectory, "sql.ini");
- sysPaths[1] = Path.Combine(Environment.GetEnvironmentVariable("windir"), @"system32\sql.ini");
- sysPaths[2] = Path.Combine(Environment.GetEnvironmentVariable("windir"), @"system\sql.ini");
- sysPaths[3] = Path.Combine(Environment.GetEnvironmentVariable("windir"), "sql.ini");
- string iniPath = string.Empty;
- for (int i = 0; i < sysPaths.Length; i++)
- {
- if (File.Exists(sysPaths[i]))
- {
- iniPath = sysPaths[i];
- break;
- }
- }
- if (string.IsNullOrEmpty(iniPath)) // We haven't found the SQL.ini file yet...
- {
- string[] environmentPaths = Environment.GetEnvironmentVariable("PATH").Split(';');
- for (int i = 0; i < environmentPaths.Length; i++)
- {
- if (File.Exists(Path.Combine(environmentPaths[i], "sql.ini")))
- {
- iniPath = Path.Combine(environmentPaths[i], "sql.ini");
- break;
- }
- }
- }
- if (!string.IsNullOrEmpty(iniPath))
- {
- // Test Name in SqlServer
- string connstring = INIRead("sqlserver", database, iniPath);
- string[] strs = connstring.Split(',');
- if (strs.Length == 2)
- {
- sqlINIEntry.DatabaseType = DatabaseTypeEnum.SqlServer;
- sqlINIEntry.ServerName = strs[0];
- sqlINIEntry.DatabaseName = strs[1];
- return sqlINIEntry; // Return if found
- }
- // Test Oracle next
- string[] oraGtwy = GetPrivateProfileSection("oragtwy", iniPath);
- if (oraGtwy != null)
- {
- foreach (string section in oraGtwy)
- {
- string REMOTEDBNAMEString = "REMOTEDBNAME=" + database.ToUpper() + ",@";
- if (section.ToUpper().StartsWith(REMOTEDBNAMEString))
- {
- sqlINIEntry.DatabaseType = DatabaseTypeEnum.Oracle;
- string dbName = section.ToUpper().Replace(REMOTEDBNAMEString, "");
- sqlINIEntry.ServerName = dbName;
- sqlINIEntry.DatabaseName = dbName;
- return sqlINIEntry; // Return if found
- }
- }
- }
- sqlINIEntry.WarningMessage = "Can't find database name: '" + database + "' in file: " + iniPath;
- }
- else
- sqlINIEntry.WarningMessage = "Can't find 'sql.ini' file.";
- return sqlINIEntry;
- }
- catch (Exception ex)
- {
- throw new Exception("Can't find or parse 'sql.ini' file in ParseSqlIni!" + Environment.NewLine + ex.Message + Environment.NewLine + ex.Source);
- }
- }
- #endregion
- }
- }
Run your own SQL Query
- [TestMethod]
- public void TestSQLCommand()
- {
- Synergy.BusinessObjects.DatabaseConnection Database = null;
- try
- {
- Database = ConnectToDbase();
- if (Database.Connected)
- {
- IDbCommand SQLCmd = Database.CreateNewCommand;
- SQLCmd.CommandText = "SELECT COUNT(*) FROM PART";
- object CmdReturn = SQLCmd.ExecuteScalar(); // Oracle returns a decimal, sql an int
- if (CmdReturn != DBNull.Value)
- {
- int PartCnt = 0;
- int.TryParse(CmdReturn.ToString(), out PartCnt);
- Assert.IsTrue(PartCnt > 0, "Fail, Perhaps you have no parts in dbo.PART?");
- }
- else
- Assert.Fail("Perhaps you have no Parts.");
- }
- else
- Assert.Fail("Datbase Connection Failed, Check App.config");
- }
- catch (Exception ex)
- {
- Assert.Fail(ex.Message);
- }
- finally
- {
- if (Database != null) Database.Transaction = null;
- }
- }
- [TestMethod]
- public void ReadSite()
- {
- Synergy.BusinessObjects.DatabaseConnection Database = null;
- try
- {
- Database = ConnectToDbase();
- if (Database.Connected)
- {
- Synergy.BusinessObjects.VE.SITE Site = new Synergy.BusinessObjects.VE.SITE(Database);
- Site.ID = "%";
- int Count = 0;
- foreach (Synergy.BusinessObjects.VE.SITE Rec in Site.LoadLike(Site))
- {
- Count += 1;
- }
- Assert.IsTrue(Count > 0, "Fail, did not find any Site records");
- }
- else
- Assert.Fail("Datbase Connection Failed, Check App.config");
- }
- catch (Exception ex)
- {
- Assert.Fail(ex.Message);
- }
- finally
- {
- if (Database != null) Database.Transaction = null;
- }
- }
Read a Customer Record
In this sample the code will read all customer records. Including the ones that are no longer active.
- [TestMethod]
- public void ReadCustomer()
- {
- Synergy.BusinessObjects.DatabaseConnection Database = null;
- try
- {
- Database = ConnectToDbase();
- if (Database.Connected)
- {
- Synergy.BusinessObjects.VE.CUSTOMER Customer = new Synergy.BusinessObjects.VE.CUSTOMER(Database);
- Customer.ID = "%";
- int Count = 0;
- foreach (Synergy.BusinessObjects.VE.CUSTOMER Rec in Customer.LoadLike(Customer))
- {
- Count += 1;
- }
- Assert.IsTrue(Count > 0, "Fail! Could not find any Customer records.");
- }
- else
- Assert.Fail("Datbase Connection Failed, Check App.config");
- }
- catch (Exception ex)
- {
- Assert.Fail(ex.Message);
- }
- finally
- {
- if (Database != null) Database.Transaction = null;
- }
- }
Read Application Global
- [TestMethod]
- public void ReadApplication_Global()
- {
- Synergy.BusinessObjects.DatabaseConnection Database = null;
- try
- {
- Database = ConnectToDbase();
- if (Database.Connected)
- {
- APPLICATION_GLOBAL AppGlobal = new APPLICATION_GLOBAL(Database);
- AppGlobal = AppGlobal.Load(1);
- Assert.IsTrue(!string.IsNullOrEmpty(AppGlobal.COMPANY_NAME), "Fail! Check app global for a company name");
- }
- else
- Assert.Fail("Datbase Connection Failed, Check App.config");
- }
- catch (Exception ex)
- {
- Assert.Fail(ex.Message);
- }
- finally
- {
- if (Database != null) Database.Transaction = null;
- }
- }
Create a Customer Order
- [TestMethod]
- public void CreateCustomerOrder()
- {
- Synergy.BusinessObjects.DatabaseConnection Database = null;
- try
- {
- Database = ConnectToDbase();
- if (Database.Connected)
- {
- CUSTOMER_ORDER CustOrd = new CUSTOMER_ORDER(Database)
- {
- SITE_ID = "101AMC",
- CUSTOMER_ID = "C-00001",
- STATUS = "R" //release it so we can ship it below.
- };
- CustOrd.Save(); //Save it and you get the auto-generated ID
- Assert.IsTrue(!string.IsNullOrEmpty(CustOrd.ID), "Fail! Did not create an order for customer 'C-00001'");
- }
- else
- Assert.Fail("Datbase Connection Failed, Check App.config");
- }
- catch (Exception ex)
- {
- Assert.Fail(ex.Message);
- }
- finally
- {
- if (Database != null) Database.Transaction = null;
- }
- }
Create a Voucher
There is a sample program, StarterMultiSite, that includes, or may be similar to, the following code:

- PAYABLE Voucher = new PAYABLE(_Database);
- Voucher.SITE_ID = txtSiteId.Text;
- Voucher.INVOICE_ID = txtInvoiceId.Text;
- Voucher.VENDOR_ID = txtVendorId.Text;
- Voucher.INVOICE_DATE = dtInvoiceDate.Value;
- Voucher.TOTAL_AMOUNT = Convert.ToDecimal(txtTotalAmount.Text);
- // Voucher.POSTING_DATE = dtPostingDate.Value; // This should be set at time of posting
- PAYABLE_LINE Line = new PAYABLE_LINE(_Database);
- Line.PURC_ORDER_ID = txtPOrder.Text; ;
- Line.PURC_ORDER_LINE_NO = Convert.ToDecimal(txtLineNmbr.Text);
- Line.QTY = Convert.ToDecimal(txtLineQty.Text);
- Line.PO_UNIT_PRICE = Convert.ToDecimal(txtPOUnitPrice.Text);
- Line.AMOUNT = Convert.ToDecimal(txtPOUnitPrice.Text) * Line.QTY; // Calculate the total line amount
- Line.RECEIVER_ID = txtReceiverId.Text;
- Line.RECEIVER_LINE_NO = Convert.ToDecimal(txtReceiverLine.Text);
- // Line.GL_ACCOUNT_ID =
- Voucher.Lines.Add(Line);
- Voucher.Save();
- MessageBox.Show(this, "Voucher Created", "Create Voucher", MessageBoxButtons.OK);
Create Customer Order with a Work Order
There is a sample program, StarterMultiSite, that includes, or may be similar to, the following code:

- using (new HourGlass())
- {
- try
- {
- // Create a Customer Order
- CUSTOMER_ORDER co = new CUSTOMER_ORDER(_Database)
- {
- #if MultiSite
- SITE_ID = "MMC",
- #endif
- CUSTOMER_ID = "FINMAN",
- STATUS = "R" //release it so we can ship it below.
- };
- co.Save(); //Save it and you get the auto-generated ID
- txtCustOrderId.Text = co.ID;
- txtCustOrderToShip.Text = co.ID;
- //Create an Order Line
- CUST_ORDER_LINE col = new CUST_ORDER_LINE(co)
- {
- #if MultiSite
- SITE_ID = co.SITE_ID,
- #endif
- PART_ID = "PRODUCT_P",
- USER_ORDER_QTY = 3,
- SELLING_UM = "EA"
- };
- col.Save();
- CUSTOMER_ORDER co1 = co.Load(co.ID);
- int foo = co1.Lines.Count;
- CUSTOMER_ORDER coLoader = new CUSTOMER_ORDER(_Database) { ID = "0200%" };
- List<CUSTOMER_ORDER> CoList = co.LoadLike(coLoader);
- foreach (CUSTOMER_ORDER c in CoList)
- {
- int foo2 = c.Lines.Count;
- }
- //Create a Work Order with an operation and a material
- WORK_ORDER wo = new WORK_ORDER(_Database)
- {
- #if MultiSite
- SITE_ID = "MMC",
- #endif
- TYPE = "W",
- //wo.BASE_ID = "00_SS1"; //Don't set for auto number gen - NEXT_NUMBER_GEN table
- LOT_ID = "0",
- SPLIT_ID = "0",
- SUB_ID = "0",
- PART_ID = col.PART_ID
- };
- wo.DESIRED_QTY = wo.DESIRED_QTY;
- //wo.Save();
- //Create an operation on the WO
- OPERATION op = new OPERATION(wo)
- {
- #if MultiSite
- SITE_ID = wo.SITE_ID,
- #endif
- SEQUENCE_NO = 10,
- RESOURCE_ID = "DRILL"
- };
- //op.Save();
- wo.OPERATIONS.Add(op);
- //Add a material to the OPERATION
- REQUIREMENT req = new REQUIREMENT(op)
- {
- #if MultiSite
- SITE_ID = op.SITE_ID,
- #endif
- PART_ID = "1/4plate"
- };
- //req.Save();
- op.REQUIREMENTS.Add(req);
- wo.Save();
- txtWorkOrderId.Text = wo.BASE_ID;
- //
- //Connect the Demand fron the CO Line to the Supply from the WO
- //
- DEMAND_SUPPLY_LINK dsl = new DEMAND_SUPPLY_LINK(_Database)
- {
- SUPPLY_TYPE = "WO",
- #if MultiSite
- SUPPLY_SITE_ID = wo.SITE_ID,
- #endif
- SUPPLY_BASE_ID = wo.BASE_ID,
- SUPPLY_LOT_ID = wo.LOT_ID,
- SUPPLY_SPLIT_ID = wo.SPLIT_ID,
- SUPPLY_SUB_ID = wo.SUB_ID,
- DEMAND_TYPE = "CO",
- #if MultiSite
- DEMAND_SITE_ID = co.SITE_ID,
- #endif
- DEMAND_BASE_ID = co.ID,
- DEMAND_SEQ_NO = col.LINE_NO,
- ALLOCATED_QTY = wo.DESIRED_QTY
- };
- dsl.Save(); //Save and the link is made
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.ToString());
- }
- }
Delete a Packlist with SBO
The following code snippet demonstrates how to delete a Shipper, (Pack list), from the Infor Visual ERP database.
- public bool Delete_Packlist(string packlist_id)
- {
- DatabaseConnection _Database;
- bool result = true;
- try
- {
- // Add DB connection specific code here.
- using (IDbConnection conn = _Database.Connection)
- {
- conn.Open();
- SHIPPER s = new SHIPPER(_Database).Load(packlist_id);
- s.Delete();
- s.Save();
- }
- }
- catch (Exception ex)
- {
- _Database.Transaction?.Rollback();
- result = false;
- }
- finally
- {
- _Database.Transaction?.Dispose();
- _Database.Transaction = null;
- }
- return result;
- }
Working with Authentication Server
For customers who have a licensed version of sbo objects, you will need to go through Authentication server for credentials. you will then communicate with the sbo objects using this _Database (sample connection below) connection.
- private DatabaseConnection _Database;
- public DatabaseConnection Database
- {
- get
- {
- if (_Database == null)
- {
- _Database = new DatabaseConnection("http://localhost/AuthenticationService.asmx");
- _Database.UserCredentials.DatabaseType = DatabaseEngineType.SqlServer;
- _Database.UserCredentials.Server = "yourservernamehere";
- _Database.UserCredentials.Database = "your database VMFG here";
- _Database.UserCredentials.UserID = "your program UserId here";
- _Database.UserCredentials.Password = "your program UserId password here";
- _Database.UserCredentials.ConnectionStringAppend = "Trusted_Connection=False;Encrypt=False;";
- }
- if (!_Database.Connected) _Database.Connect();
- if (!_Database.Connected) MessageBox.Show(this,"No Connection","Database Connection", MessageBoxButtons.OK);
- return _Database;
- }
- }
A call would look similar to:
- CUSTOMER_ORDER CustOrder = new CUSTOMER_ORDER(Database)
Working with WM-Synergy Macro Server
Creating a callable library
When creating a library, (.dll), module the important thing to know is that there are 2 required Public Properties that must be a part of the class file.
- public class MyClass
- {
- #region MacroServer
- public string ServerURL { get; set; } //Url to ServerLib of MacroServer
- public string Key { get; set; } // Encrypted Database Key
- internal MacroServer MacroServer
- {
- get
- {
- if (_MacroServer == null)
- {
- _MacroServer = new MacroServer(ServerURL, Key);
- }
- return _MacroServer;
- }
- }
- #endregion
A typical WM-Synergy macro call would look like the following:
- dim obj
- lib.ActivateObject "obj", "MyFamousibrary.dll", "MyFamouslibrary.MyClass"
- set obj = lib.GetObject("obj")
- obj.Key = util.authenticationHash
- obj.ServerURL = util.ServerURL & "/ServerLib.asmx"
- obj.DatabaseType = "SQLServer"
- obj.MyMethod
It will be important to store your library in the working directory for the Macro Server Web API.
Create a .dll for a Macro
A Visual ERP Macro must be made as a COM compliant .dll. In order to do this, the developer should set the following at the project level:
The next step is to set some compile directives on your base class for the .dll
It is suggested to avoid a Constructor as it may cause issues when loading the .dll (you should validate if it is an issue with your design)
- [ComVisible(true)] // Expose the class
- [ClassInterface(ClassInterfaceType.None)] // Select None, as we want to specify what is to be exposed.
- [Guid("5b37be8d-293c-46ba-9503-a4ac961b7101")] // not required would auto pull from project guid
- [ProgId("CreatePPGSRequests.CreatePPGSRequests")] // suggested, should match with how it would be evoked.
- public class CreatePPGSRequests
- {
- #region Private Variables
- private MacroServer _MacroServer = null;
- private DatabaseConnection _Database = null;
- #endregion
- #region MacroServer Required Properties
- [ComVisible(true)] // Place these here to ensure the program is making visible to com call those items you want visible
- public string Key { get; set; } // Key for Authenticator
- [ComVisible(true)]
- public string ServerURL { get; set; } // MacroServer Authenticator
- [ComVisible(true)]
- public string DatabaseType { get; set; } // SQLServer vs Oracle
- internal MacroServer MacroServer
- {
- get
- {
- if (_MacroServer == null)
- {
- _MacroServer = new MacroServer(ServerURL, Key);
- }
- return _MacroServer;
- }
- }
- internal string ServerXMLURL
- {
- get
- {
- return string.Format("{0}/Credentials/{1}.xml", Regex.Replace(ServerURL, "/Serverlib.asmx", "", RegexOptions.IgnoreCase), Key);
- }
- }
- #endregion
For each public method, make sure to add the [ComVisible(true)], this ensures that this method will be available to the vbscript.
These extra steps help to ensure that when the project Make project com visible, is actually making visible those objects that you as a developer need exposed to the calling vbscript code base.
- #region Public Methods
- /// <summary>
- /// <c>ProcessWorkOrder</c>
- /// <para>Create the PPGS OrderImport requests, and move inentory to a temporary holding area,
- /// until the PPGS has completed all the pulls for the given Pick.</para>
- /// </summary>
- /// <param name="SiteId"></param>
- /// <param name="WorkOrder"></param>
- /// <returns>true if success</returns>
- [ComVisible(true)]
- public bool ProcessWorkOrder(string SiteId, string WorkOrder, string UserId)
- { ...
Sample Macro Call
When creating an SRI style macro for use with Visual ERP, make sure your .dll can be found from a directory withing Macro Server Web API directory.
- Dim obj
- lib.ActivateObject "obj","YourSubDirectory/MyFamousDll.dll","MyFamousDll.Client" // Note the direction of the '/' as this is going through MacroServerer API.
- set obj = lib.GetObject ( "obj" ) // Instantiate the Reflection into your .dll method
- obj.Key = util.authenticationHash // Your .dll must have a propert for Key
- obj.ServerUrl = util.ServerURL // Your .dll must have a property for ServerUrl
- obj.LoadForm ORDER_ID
.dll Code Template for your Visual ERP Macro method call
- #region MacroServer Required Properties
- public string Key { get; set; } // Key for Authenticator
- public string ServerURL { get; set; } // MacroServer Authenticator
- #endregion
If using sbo objects with your .dll then use the following code snippet to connect sbo objects
- private DataBaseConnection _Database = null;
- public bool Client()
- {
- _Database = new DatabaseConnection();
- _Database.UserCredentials.MacroServerXmlUrl = $"{ServerURL.Replace("/Serverlib.asmx", "")}/Credentials/{Key}.xml";
- _Database.Connect();
- using (SqlCommand SqlCmd = (SqlCommand)_Database.CreateNewCommand)
- {
- SqlCmd.CommandText = $@"SELECT DBVERSION FROM APPLICATION_GLOBAL";
- if (Convert.ToString(SqlCmd.ExecuteScalar()) != "9.0.8")
- {
- MessageBox.Show(this,"This code only works with Visual ERP 9.0.8","Connect to Server");
- return false;
- }
- ...
Interface with Database Server
There are two methods that can be used when your application needs to connect to the database
- Connect through MacroServer
- Connect through Synergy BusinessObjects
MacroServer
Given a connection to the Macro Server, try the following:
- string SqlCmd = $@"
- SELECT CODE, DESCRIPTION
- FROM {TablePrefix}.SRI_TAX_ENTITY_USE_CODES
- ";
- SRIMacroServer.ExecuteQueryResults Results = MacroServer.ExecuteQuery(SqlCmd);
SynergyBusinessObjects
Given a MacroServer connection one can try the following:
-
_Database = new DatabaseConnection(ServerURL); - #region MacroServer Required Properties
- public string Key { get; set; } // Key for Authenticator
- public string ServerURL { get; set; } // MacroServer Authenticator
- public string DatabaseType { get; set; } // SQLServer vs Oracle
- internal MacroServer MacroServer
- {
- get
- {
- if (_MacroServer == null)
- {
- _MacroServer = new MacroServer(ServerURL, Key);
- }
- return _MacroServer;
- }
- }
- internal string ServerXMLURL
- {
- get
- {
- return string.Format("{0}/Credentials/{1}.xml", Regex.Replace(ServerURL, "/Serverlib.asmx", "", RegexOptions.IgnoreCase), Key);
- }
- }
- #endregion
- public void myMethod()
{ - _Database = new DatabaseConnection();
- _Database.UserCredentials.MacroServerXmlUrl = ServerXMLURL;
- _Database.UserCredentials.ConnectionStringAppend = "TrustServerCertificate=True";
- _Database.Connect();
- _Database.Transaction = _Database.Connection.BeginTransaction();
- StringBuilder SqlCmd = new StringBuilder();
- SqlCmd.Append("SELECT TOP(1) [TempWarehouse], [TempLocation], [AutoProcess], [AutoEmail] FROM dbo.[SRI_TravelerConfig]");
- IDbCommand GetCommand = _Database.CreateNewCommand;
- GetCommand.CommandText = SqlCmd.ToString();
- IDataReader RecReader = GetCommand.ExecuteReader();
Errors
A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)
If your SQL Server is using a self-signed certificate, it won't be trusted by default. You can either disable encryption or trust the self-signed certificate.
Solution: Add TrustServerCertificate=True to your connection string.
Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;TrustServerCertificate=True;
If the certificate is from a non-trusted authority, you need to add it to the Trusted Root Certification Authorities store on the client machine.
Solution: Export the server certificate and install it on the client machine2.
Export the server certificate using MMC.
Import it into the Trusted Root Certification Authorities store on the client machine.
As a quick fix, you can disable encryption in your connection string, but this is not recommended for production environments.
Solution: Add Encrypt=False to your connection string3.
Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;Encrypt=False;
By following these steps, you can resolve the SSL provider error and establish a secure connection to your SQL Server.