I used the Linked Table Wizard to create the code for the table, then added the Class Method as a way to query the table in the one case...

/// Generated by the Link Table wizard on 2020-12-07 13:29:25.  Note that you can access the data in this class only when the external database is accessible.

Class osuwmc.CPD.vProviderNPIEns Extends %Library.Persistent [ Not ProcedureBlock, SqlRowIdPrivate, SqlTableName = vProviderNPIEns, StorageStrategy = GSQLStorage ]

{

/// Specifies details for the SQL Gateway Connection that this class uses

Parameter CONNECTION = "jTDS-CPD-Prod,NOCREATE";

/// Specifies the external database that this class uses

Parameter EXTDBNAME = "Microsoft SQL Server";

/// Determines if INSERT statements for this external table attempt to retrieve auto-generated keys.  Set this to 0 if this external table does not support auto generated keys.

Parameter EXTERNALGENERATEDKEYS = 1;

/// Specifies the external table to which this class refers

Parameter EXTERNALTABLENAME = "dbo.vProvider_NPI_Ens";

Property DoctorNumber As %String(EXTERNALSQLNAME = "DoctorNumber", EXTERNALSQLTYPE = 1, MAXLEN = 6) [ ReadOnly, Required, SqlColumnNumber = 2, SqlFieldName = DoctorNumber ];

Property NPI As %String(EXTERNALSQLNAME = "NPI", EXTERNALSQLTYPE = 12, MAXLEN = 10) [ ReadOnly, SqlColumnNumber = 3, SqlFieldName = NPI ];

Index MainIndex On (DoctorNumber, NPI) [ IdKey, PrimaryKey ];

Index ProviderDoctorNumber On DoctorNumber;

ClassMethod FindNPI(DoctorNumber As %String) As %String [ SqlProc ]

{

  set NPI = ""

  &sql(SELECT NPI into :NPI

    FROM osuwmc_CPD.vProviderNPIEns WHERE DoctorNumber=:DoctorNumber)

   

  IF SQLCODE <0 {write "SQLCODE error ",SQLCODE," ",%msg QUIT}

  ELSEIF SQLCODE = 100 {write "Query return no results" QUIT}

  quit NPI

}

Storage GSQLStorage

{

<ExtentSize>111002</ExtentSize>

<Property name="%%ID">

<Selectivity>1</Selectivity>

</Property>

<StreamLocation>^osuwmc.CPD.vProviderNPIEnsS</StreamLocation>

<Type>%Storage.SQL</Type>

}

}

In the Second Case I used the Linked Table Wizard, but call the sql code from the DTL, so I am not sure how that would be an issue.

I see what you mean in 2022.1 it will not compile but however it does compile in 2018.1.3.

2022.1

Compilation started on 05/02/2023 08:05:23 with qualifiers 'cuk'

Compiling class osuwmc.AlertEmail

Compiling routine osuwmc.AlertEmail.1

ERROR: osuwmc.AlertEmail.cls

ERROR:  osuwmc.AlertEmail.1(13) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' in system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",2740803238),/ensemble/TEST/mgr/enslib/' on node '%3'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set pMailMessage.Subject = pMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' in system '%2' on node '%3'""","""Ensemble"""))),pAlertRequest.SourceConfigName,tSystemName,tNodeName)

ERROR:  osuwmc.AlertEmail.1(16) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' on system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",3633416132),/ensemble/TEST/mgr/enslib/'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set pMailMessage.Subject = pMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble Alert from configuration item '%1' on system '%2'""","""Ensemble"""))),pAlertRequest.SourceConfigName,tSystemName)

ERROR:  osuwmc.AlertEmail.1(25) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble alert email triggered at %1 [<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",2328442859),/ensemble/TEST/mgr/enslib/ UTC]""","""Ensemble"""))' failed with an error: %2

 TEXT:    Set tTimeMessage = $select(..IncludeUTCTimes: $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble alert email triggered at %1 [%2 UTC]""","""Ensemble"""))),tNowLocal,tNow), 1 : $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble alert email triggered at %1""","""Ensemble"""))),tNowLocal))

ERROR:  osuwmc.AlertEmail.1(25) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble alert email triggered at %1""","""Ensemble"""))' failed with an error: <PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",3301903811),/ensemble/TEST/mgr/enslib/

 TEXT:    Set tTimeMessage = $select(..IncludeUTCTimes: $$FormatText^%occMessages(,tNowLocal,tNow), 1 : $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble alert email triggered at %1""","""Ensemble"""))),tNowLocal))

ERROR: osuwmc.AlertEmail.cls

ERROR:  osuwmc.AlertEmail.1(14) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' in system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",197323985),/ensemble/TEST/mgr/enslib/' on node '%3'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set tMailMessage.Subject = tMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' in system '%2' on node '%3'""","""Ensemble"""))),tManagedAlert.SourceConfigName,tSystemName,tNodeName)

ERROR:  osuwmc.AlertEmail.1(17) : MPP5646 : ##expression on '$$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' on system '<PROTECT> 202 macroText+51^%occMessages ^IRIS.Msg("Ensemble","en",466437042),/ensemble/TEST/mgr/enslib/'""","""Ensemble"""))' failed with an error: %2

 TEXT:      Set tMailMessage.Subject = tMailMessage.Subject _ $$FormatText^%occMessages(##safeexpression($$macroText^%occMessages($lb("""Ensemble ManagedAlert from configuration item '%1' on system '%2'""","""Ensemble"""))),tManagedAlert.SourceConfigName,tSystemName)

Detected 6 errors during compilation in 0.091s.

2018.1.3

Compilation started on 05/02/2023 08:13:51 with qualifiers 'cuk'

Class osuwmc.AlertEmail is up-to-date.

Compilation finished successfully in 0.199s.

Alex, 

I tried that but now I am receiveing... ERROR #5002: ObjectScript error: <UNDEFINED>zDecodeBase64HL7ToFile+22^osuwmc.Functions.1 *%C(10)

ClassMethod DecodeBase64HL7ToFile(base64 As %Stream.GlobalBinary, Ancillary As %String, FileName As %String) As %String

{

  set ArchDir = "/ensemble/data/transfer/AncillaryPDF/"

  set ArchAncDir = ArchDir_Ancillary_"/"

  set FaxDateDir = ArchAncDir_$PIECE($ZDATE($HOROLOG,7)," ",1)_"-"_$PIECE($ZDATE($HOROLOG,7)," ",2)_"-1/"

  if '##class(%Library.File).DirectoryExists(ArchDir)

  {

    do ##class(%Library.File).CreateDirectory(ArchDir)

  }

  if '##class(%Library.File).DirectoryExists(ArchAncDir)

  {

    do ##class(%Library.File).CreateDirectory(ArchAncDir)

  }

  if '##class(%Library.File).DirectoryExists(FaxDateDir)

  {

    do ##class(%Library.File).CreateDirectory(FaxDateDir)

  }

  set Oref = ##class(%FileBinaryStream).%New()

  ///$$$LOGINFO(FaxDateDir_FileName)

  set Oref.Filename = FaxDateDir_FileName

  Do base64.Rewind()

  While 'base64.AtEnd {

      set ln = base64.ReadLine()

      set:ln[%C(10) base64.LineTerminator=$C(10)

      set lnDecoded = $system.Encryption.Base64Decode(ln)

    do Oref.Write(lnDecoded)

  }

  Do Oref.%Save()

  set PDFFilePath = FaxDateDir_FileName

  return PDFFilePath

}

I am also seeing this error when Decoding Base 64 and writing the contents out to a file on the file system. Can I not return a String to the DTL?

ClassMethod DecodeBase64HL7ToFile(base64 As %Stream.GlobalBinary, Ancillary As %String, FileName As %String) As %String

{

  set ArchDir = "/ensemble/data/transfer/AncillaryPDF/"

  set ArchAncDir = ArchDir_Ancillary_"/"

  set FaxDateDir = ArchAncDir_$PIECE($ZDATE($HOROLOG,7)," ",1)_"-"_$PIECE($ZDATE($HOROLOG,7)," ",2)_"-1/"

  if '##class(%Library.File).DirectoryExists(ArchDir)

  {

    do ##class(%Library.File).CreateDirectory(ArchDir)

  }

  if '##class(%Library.File).DirectoryExists(ArchAncDir)

  {

    do ##class(%Library.File).CreateDirectory(ArchAncDir)

  }

  if '##class(%Library.File).DirectoryExists(FaxDateDir)

  {

    do ##class(%Library.File).CreateDirectory(FaxDateDir)

  }

  set Oref = ##class(%FileBinaryStream).%New()

  ///$$$LOGINFO(FaxDateDir_FileName)

  set Oref.Filename = FaxDateDir_FileName

  Do base64.Rewind()

  While 'base64.AtEnd {

      set ln = base64.ReadLine()

      set lnDecoded = $system.Encryption.Base64Decode(ln)

    do Oref.Write(lnDecoded)

  }

  Do Oref.%Save()

  set PDFFilePath = FaxDateDir_FileName

  return PDFFilePath

}

By Adding a timeout of 2, and setting the force flag I was able to get it down from 18 min to roughly 11 min. If I remove the timeout and force flag, and watched the output I could possibly find those problematic children. I wonder if using Ens.Job would be any easier as the objects have been disabled its a matter of getting the Jobs to stop and send the unbind. 

Has anyone used Ens.Jobs before to quickly bring down a Namespace in a controlled environment? We need to unsure the unbinds are sent so we can move to a new IP address on a different section of the network.

Using the suggestions below, looping through the Config Items doesn't appear to be the issue. I ran into an issue with the UpgradeProduction. In total it took 18 min to shutdown all the Services in just one namespace when I looped through all the Config Items, disabled them, and then Updated the Production with no timeout or force to shut them down. Is there a way to make UpgradeProduction run faster beside setting the timeout or force?

I need to be able to loop through all the Services/Operations to shut them down to ensure that the TCP Disconnect is sent. 

We had a consultant create us a script that uses Regex to loop through and shutdown those Services/Operations, but running the script to bring everything down takes a good 10 min or so to disable all the Service Operation Objects.

In testing the cut over when we did our Test Environment in total it took us 20 min to bring down Ensemble (2018.1.3) and bring up IRIS (2022.1) with the network changes.

But we forgot this step and had to ask different systems to restart their Interfaces because they were still hung on the previous connections and don't have framework to realize the connection was no longer connected.

Is there a way to be able to cutdown the response time of EnableConfig item?

I tried the open also. But I did find a work around by resetting the ##class(%File).SetAttributes which is basically doing a chmod but at the ObjectScript level when creating/appending to the file. 

So what is %Stream really doing, is it just creating a new file based on what is in memory? Is it just reading the entire file into Memory so the IO is cut down and creating a new file from what is in Memory?

We have gone through all the permission settings at the directory and user level. We do not believe it is an unmask issue as the file is ok when it is first created, but the subsequent writes cause the permissions to change. If it was an unmask issue wouldn't the file have the wrong permissions in the first place? And I confirmed its not a user issue as its been duplicated with the owner of the directory and others within the same group.

Instead of MoveToOpen is there a way to use Open the file and go to the end of the file to insert the data? I tried looking at %File but could not figure out now to append data to the end of the file I just kept overwriting data.