diff --git a/B-24302 UV Case Type Family Updates.linq b/B-24302 UV Case Type Family Updates.linq
new file mode 100644
index 0000000..27526f0
--- /dev/null
+++ b/B-24302 UV Case Type Family Updates.linq
@@ -0,0 +1,566 @@
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+void Main()
+{
+ var data = @"CaseTypeFamily Name SkipICD ICD10Code MSDRGCode
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0070 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0370 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0470 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1070 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1370 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1470 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4070 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4370 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43K0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4470 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44A0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44J0 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44K0 471
+M-421 1 Cervical Level Open Approach FALSE XRG0092 471
+M-421 1 Cervical Level Open Approach FALSE XRG00F3 471
+M-421 1 Cervical Level Open Approach FALSE XRG1092 471
+M-421 1 Cervical Level Open Approach FALSE XRG10F3 471
+M-421 1 Cervical Level Open Approach FALSE XRG4092 471
+M-421 1 Cervical Level Open Approach FALSE XRG40F3 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0071 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG007J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0371 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG037J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0471 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG047J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1071 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG107J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1371 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG137J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1471 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG147J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4071 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG407J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4371 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG437J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43KJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4471 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG447J 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44AJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44J1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44JJ 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44K1 471
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44KJ 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2070 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20A0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20J0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20K0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2370 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23A0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23J0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23K0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2470 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24A0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24J0 471
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24K0 471
+M-424 2+ Cervical Level Open Approach FALSE XRG2092 471
+M-424 2+ Cervical Level Open Approach FALSE XRG20F3 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2071 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG207J 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20AJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20J1 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20JJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20K1 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20KJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2371 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG237J 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23AJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23J1 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23JJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23K1 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23KJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2471 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG247J 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24AJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24J1 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24JJ 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24K1 471
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24KJ 471
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0070 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0370 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0470 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1070 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1370 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1470 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4070 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4370 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43K0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4470 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44A0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44J0 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44K0 472
+M-421 1 Cervical Level Open Approach FALSE XRG0092 472
+M-421 1 Cervical Level Open Approach FALSE XRG00F3 472
+M-421 1 Cervical Level Open Approach FALSE XRG1092 472
+M-421 1 Cervical Level Open Approach FALSE XRG10F3 472
+M-421 1 Cervical Level Open Approach FALSE XRG4092 472
+M-421 1 Cervical Level Open Approach FALSE XRG40F3 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0071 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG007J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0371 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG037J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0471 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG047J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1071 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG107J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1371 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG137J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1471 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG147J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4071 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG407J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4371 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG437J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43KJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4471 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG447J 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44AJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44J1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44JJ 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44K1 472
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44KJ 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2070 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20A0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20J0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20K0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2370 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23A0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23J0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23K0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2470 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24A0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24J0 472
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24K0 472
+M-424 2+ Cervical Level Open Approach FALSE XRG2092 472
+M-424 2+ Cervical Level Open Approach FALSE XRG20F3 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2071 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG207J 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20AJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20J1 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20JJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20K1 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20KJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2371 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG237J 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23AJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23J1 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23JJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23K1 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23KJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2471 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG247J 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24AJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24J1 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24JJ 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24K1 472
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24KJ 472
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0070 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG00K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0370 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG03K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG0470 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG04K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1070 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG10K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1370 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG13K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG1470 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG14K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4070 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG40K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4370 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG43K0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG4470 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44A0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44J0 473
+M-420 1 Cervical Level Anterior Approach FALSE 0RG44K0 473
+M-421 1 Cervical Level Open Approach FALSE XRG0092 473
+M-421 1 Cervical Level Open Approach FALSE XRG00F3 473
+M-421 1 Cervical Level Open Approach FALSE XRG1092 473
+M-421 1 Cervical Level Open Approach FALSE XRG10F3 473
+M-421 1 Cervical Level Open Approach FALSE XRG4092 473
+M-421 1 Cervical Level Open Approach FALSE XRG40F3 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0071 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG007J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG00KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0371 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG037J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG03KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG0471 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG047J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG04KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1071 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG107J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG10KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1371 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG137J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG13KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG1471 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG147J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG14KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4071 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG407J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG40KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4371 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG437J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG43KJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG4471 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG447J 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44AJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44J1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44JJ 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44K1 473
+M-422 1 Cervical Level Posterior Approach FALSE 0RG44KJ 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2070 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20A0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20J0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG20K0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2370 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23A0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23J0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG23K0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG2470 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24A0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24J0 473
+M-423 2+ Cervical Level Anterior Approach FALSE 0RG24K0 473
+M-424 2+ Cervical Level Open Approach FALSE XRG2092 473
+M-424 2+ Cervical Level Open Approach FALSE XRG20F3 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2071 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG207J 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20AJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20J1 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20JJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20K1 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG20KJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2371 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG237J 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23AJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23J1 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23JJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23K1 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG23KJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG2471 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG247J 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24AJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24J1 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24JJ 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24K1 473
+M-425 2+ Cervical Level Posterior Approach FALSE 0RG24KJ 473";
+
+ var rows = data.Split("\n".ToCharArray())
+ .Skip(1)
+ .ToList()
+ .ConvertAll(d => new NewCaseTypeFamilyMapping(d.Trim("\r".ToCharArray()).Split('\t')))
+ .GroupBy(d => d.CaseTypeFamily, (key, info) => new
+ {
+ CaseTypeFamily = key,
+ data = info.ToList(),
+ sql = info.Aggregate(new StringBuilder($@"
+SELECT @CaseTypeFamilyID = ctf.CaseTypeFamilyID
+FROM dss.CaseTypeFamily AS ctf
+WHERE ctf.CaseTypeFamilyGlobalID = '{key}'
+
+INSERT INTO dss.CaseTypeFamilyMappingICD10 ( CaseTypeFamilyID, SkipICD, ICD10Code, MSDRGCode, CaseTypeFamilyVersionID )
+VALUES
+"),
+ (x, y) => x.AppendLine(y.ToString())).ToString().TrimEnd(new[] { '\r', '\n', ',' }),
+ rollback = $@"DELETE FROM dss.CaseTypeFamilyMappingICD10
+WHERE EXISTS(SELECT 1 FROM dss.CaseTypeFamily AS ctf
+ WHERE ctf.CaseTypeFamilyGlobalID = '{key}' and CaseTypeFamilyMappingICD10.CaseTypeFamilyID = ctf.CaseTypeFamilyID AND CaseTypeFamilyVersionID = 1)
+DELETE FROM dss.CaseTypeFamily WHERE CaseTypeFamilyGlobalID = '{key}'
+"
+ });
+ var sqlScript = $@"--Author: tlamb
+--Version: 2019.42
+--Forward
+DELETE
+FROM dss.CaseTypeFamilyMappingICD10
+WHERE EXISTS(SELECT 1
+FROM dss.CaseTypeFamily AS ctf
+WHERE ctf.CaseTypeFamilyID = CaseTypeFamilyMappingICD10.CaseTypeFamilyID AND ctf.CaseTypeFamilyGlobalID = 'M-61')
+AND CaseTypeFamilyMappingICD10.MSDRGCode IN('471','472','473')
+AND CaseTypeFamilyMappingICD10.SkipICD = 1
+AND CaseTypeFamilyMappingICD10.CaseTypeFamilyVersionID = 1
+
+INSERT INTO dss.CaseTypeFamily(CaseTypeFamilyGUID, Name, CaseTypeFamilyGlobalID)
+VALUES(NEWID(), '1 Cervical Level Anterior Approach', 'M-420'),
+(NEWID(), '1 Cervical Level Open Approach', 'M-421'),
+(NEWID(), '1 Cervical Level Posterior Approach', 'M-422'),
+(NEWID(), '2+ Cervical Level Anterior Approach', 'M-423'),
+(NEWID(), '2+ Cervical Level Open Approach', 'M-424'),
+(NEWID(), '2+ Cervical Level Posterior Approach', 'M-425')
+
+DECLARE @CaseTypeFamilyID INT
+
+{string.Join("\r\n", rows.Select(r => r.sql))}
+--Rollback
+{string.Join("\r\n", rows.Select(r => r.rollback))}";
+
+ sqlScript.Dump("script");
+ File.WriteAllText(@"D:\git\2019-10-01-11-14 B-24302 UV Case Type Family Updates.sql", sqlScript);
+ rows.Dump();
+
+ // var sql = rows.Aggregate(new StringBuilder("DECLARE @CaseTypeFamilyID INT"),
+ // (x, y) => x.AppendLine(
+ // data.Aggregate(new StringBuilder($"SELECT @CaseTypeFamilyID = ctf.CaseTypeFamilyID FROM dss.CaseTypeFamily AS ctf WHERE ctf.CaseTypeFamilyGlobalID = '{y.CaseTypeFamily}'"),
+ // (a, b) => a.AppendLine(b.ToString())).ToString())).ToString();
+ // sql.Dump();
+}
+
+// Define other methods and classes here
+
+public class NewCaseTypeFamilyMapping
+{
+ public string CaseTypeFamily { get; set; }
+ public string Name { get; set; }
+ internal bool bSkipICD { get; set; }
+ public int SkipICD => bSkipICD ? 1 : 0;
+ public string ICD10Code { get; set; }
+ public string MSDRGCode { get; set; }
+
+ public NewCaseTypeFamilyMapping(string[] data)
+ {
+ if (data.Length != 5)
+ throw new ArgumentException(nameof(data));
+ CaseTypeFamily = data[0];
+ Name = data[1];
+ bSkipICD = bool.Parse(data[2]);
+ ICD10Code = data[3];
+ MSDRGCode = data[4];
+ }
+
+ public override string ToString()
+ {
+ //return $"\t(@CaseTypeFamilyID, '{Name}', {SkipICD}, '{ICD10Code}', '{MSDRGCode}', 1),";
+ return $"\t(@CaseTypeFamilyID, {SkipICD}, '{ICD10Code}', '{MSDRGCode}', 1),";
+ }
+}
\ No newline at end of file
diff --git a/CCI Timings.linq b/CCI Timings.linq
new file mode 100644
index 0000000..1a30f72
--- /dev/null
+++ b/CCI Timings.linq
@@ -0,0 +1,220 @@
+
+
+ 4f885e7e-d8bb-427c-a54e-8e3e1c3137a7
+ true
+ IOAK-SQL-LOG-01.sdt.local
+ jazz log prod
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+public static string PrimaryUrl => "Opportunities.aspx";
+public static string UrlGroup => "/CCI";
+public static DateTime cutoff { get; set; } = DateTime.Now.AddDays((((int)DateTime.Now.DayOfWeek) * -1) + 1).Date;
+
+void Main()
+{
+ RunTimings();
+}
+
+public void RunTimings()
+{
+ cutoff = DateTime.Now.AddDays(-30);
+ var timings = GetTimings(cutoff)
+ .Where(t => t.Key.Group == 0 && t.Data.Any());
+
+ var outliers = timings.SelectMany(t => t.Data.Where(d => d.ClientTimeData / 1000.0d > 4.0d));
+ outliers.Dump(nameof(outliers));
+
+ timings
+ .OrderByDescending(t => t.Key.ClientTimeMax > 4 ? t.Key.ClientTimeMax : 0)
+ .ThenBy(t => t.Key.Group)
+ .ThenBy(t => t.Key.Url.Contains(PrimaryUrl) ? "!" : t.Key.Url)
+ .ThenBy(t => t.Key.Application)
+ .ThenByDescending(t => t.Key.Date)
+ .ThenBy(t => t.Key.Browser.StartsWith("IE") ? 0 : 1)
+ .Dump();
+}
+
+public IEnumerable GetTimings(DateTime cutoff)
+{
+ return from log in Archive_PageLogs
+ where (log.Url.StartsWith(UrlGroup))
+ && log.DateTimeStamp > cutoff
+ group log by new { Group = (log.UserName.StartsWith("sdt\\") ? 1 : 0), log.Url, log.Browser, Date = log.DateTimeStamp.Value.Date, log.Application } into grp
+ //join dbs in ViewActiveDatabases on grp.FirstOrDefault().DatabaseGuid equals dbs.DatabaseGUID
+ orderby grp.Key.Group, (grp.FirstOrDefault().ClientTime / 1000) descending, grp.Key.Date descending
+ select new MetricData
+ {
+ Key = new MetricKey
+ {
+ Application = grp.Key.Application,
+ Group = grp.Key.Group,
+ Url = grp.Key.Url,
+ Browser = grp.Key.Browser,
+ Date = grp.Key.Date,
+ ClientTimeAvg = grp.ToList().Average(g => (g.ClientTime / 1000.0d)) ?? 0.0d,
+ ClientTimeMin = grp.ToList().Min(g1 => (g1.ClientTime / 1000.0d)) ?? 0.0d,
+ ClientTimeMax = grp.ToList().Max(g1 => (g1.ClientTime / 1000.0d)) ?? 0.0d,
+ Count = grp.ToList().Count
+ },
+ Data = grp
+ .Select(g => new Metric(g.DatabaseGuid.Value, ViewActiveDatabases)
+ {
+ UrlParams = g.UrlParams,
+ UserName = g.UserName,
+ WebServer = g.WebServer,
+ ServerTimeData = g.ServerTime ?? 0,
+ ClientTimeData = g.ClientTime ?? 0,
+ DatabaseName = g.DatabaseName,
+ ClientTime = g.ClientTime ?? 0 / 1000.0d,
+ ClientTimeAvg = grp.ToList().Average(g1 => g1.ClientTime ?? 0.0d / 1000.0d),
+ ClientTimeMin = grp.ToList().Min(g1 => g1.ClientTime ?? 0.0d / 1000.0d),
+ ClientTimeMax = grp.ToList().Max(g1 => g1.ClientTime ?? 0.0d / 1000.0d)
+ }).Where(x => (x.ClientTimeData / 1000.0d) > x.ClientTimeAvg || ((x.ClientTimeData / 1000.0d) > 4.0d))
+ };
+}
+
+// Define other methods and classes here
+
+public class Metric
+{
+ public double ClientTime { get; set; }
+ public double ClientTimeData { get; set; }
+ public double ClientTimeAvg { get; set; }
+ public double ClientTimeMin { get; set; }
+ public double ClientTimeMax { get; set; }
+ public string WebServer { get; set; }
+ public string PhysicalName { get; set; }
+ public Guid DatabaseGuid { get; set; }
+ public string DatabaseName { get; set; }
+ public string UserName { get; set; }
+ public string UrlParams { get; set; }
+ public int ServerTimeData { get; set; }
+ public string OrgPin { get; set; }
+
+ public Metric()
+ {
+
+ }
+
+ public Metric(Guid databaseGuid, Table activeDatabases)
+ {
+ DatabaseGuid = databaseGuid;
+ var activeDatabase = activeDatabases.SingleOrDefault(vad => vad.DatabaseGUID == databaseGuid);
+ PhysicalName = activeDatabase?.PhysicalName ?? string.Empty;
+ OrgPin = activeDatabase?.OrgPin ?? string.Empty;
+ }
+
+ object ToDump() => new
+ {
+ ClientTimeMax = new XElement("LINQPad.HTML",
+ new XElement("div",
+ new XAttribute("align", "right"),
+ new XAttribute("style", $"background-color:{(ClientTimeMax > 4.0d ? "red" : (ClientTimeAvg < (ClientTimeData / 1000.0d)) ? "violet" : "white")};"),
+ $"{ClientTimeMax:n}".PadLeft(10))),
+ ClientTimeAvg,
+ ClientTimeMin,
+ WebServer,
+ OrgPin,
+ DatabaseName,
+ PhysicalName,
+ UserName,
+ UrlParams,
+ ServerTime = $"{ServerTimeData:n0}".PadLeft(10)
+ };
+}
+
+public class MetricKey
+{
+ public string Application { get; set; }
+ public int Group { get; set; }
+ public string Browser { get; set; }
+ public string Url { get; set; }
+ //public int UrlLength { get; set; }
+ public DateTime Date { get; set; }
+ public double ClientTimeAvg { get; set; }
+ public double ClientTimeMin { get; set; }
+ public double ClientTimeMax { get; set; }
+ public int Count { get; set; }
+
+ object ToDump() => new
+ {
+ Application,
+ GroupName = Group == 0 ? "Clients" : "Strata",
+ Browser,
+ URL = Url, //.PadRight(UrlLength),
+ OnDate = Date.ToShortDateString(),
+ Avg_ClientTime = $"{ClientTimeAvg:N2}",
+ Min_ClientTime = $"{ClientTimeMin:N2}",
+ Max_ClientTime = $"{ClientTimeMax:N2}",
+ Count
+ };
+}
+
+public class MetricData
+{
+ public MetricKey Key { get; set; }
+ public IEnumerable Data { get; set; }
+
+ object ToDump() => new
+ {
+ Group = Key,
+ Statistics = Data
+ .OrderBy(d => d.WebServer)
+ .ThenBy(d => d.DatabaseName)
+ .ThenBy(d => d.UserName)
+ .ThenBy(d => d.ClientTimeData)
+ };
+}
\ No newline at end of file
diff --git a/CI Testing Stuff/Payroll Opportunity Metric.linq b/CI Testing Stuff/Payroll Opportunity Metric.linq
new file mode 100644
index 0000000..def8ffb
--- /dev/null
+++ b/CI Testing Stuff/Payroll Opportunity Metric.linq
@@ -0,0 +1,79 @@
+
+
+void Main()
+{
+ var pom = new PayrollOpportunityMetric
+ {
+ BaselineMonth01Dollars = 1.0m,
+ ActualMonth03Dollars = 1.0m,
+ CommittedMonth06Dollars = 1.0m
+ };
+ pom.BaselineDollars().Dump();
+ pom.ActualDollars().Dump();
+ pom.CommittedDollars().Dump();
+}
+
+// Define other methods and classes here
+
+public class PayrollOpportunityMetric
+{
+ public decimal BaselineMonth01Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth02Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth03Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth04Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth05Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth06Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth07Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth08Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth09Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth10Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth11Dollars { get; set; } = 0.0m;
+ public decimal BaselineMonth12Dollars { get; set; } = 0.0m;
+
+ public decimal ActualMonth01Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth02Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth03Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth04Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth05Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth06Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth07Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth08Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth09Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth10Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth11Dollars { get; set; } = 0.0m;
+ public decimal ActualMonth12Dollars { get; set; } = 0.0m;
+
+ public decimal CommittedMonth01Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth02Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth03Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth04Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth05Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth06Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth07Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth08Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth09Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth10Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth11Dollars { get; set; } = 0.0m;
+ public decimal CommittedMonth12Dollars { get; set; } = 0.0m;
+}
+
+public static class PayrollOpportunityMetricExtensions
+{
+ public static IEnumerable BaselineDollars(this PayrollOpportunityMetric pom) =>
+ typeof(PayrollOpportunityMetric)
+ .GetProperties(BindingFlags.Instance | BindingFlags.Public)
+ .Where(p => p.Name.StartsWith("BaselineMonth") && p.Name.EndsWith("Dollars"))
+ .Select(dp => (decimal) dp.GetValue(pom, null));
+
+ public static IEnumerable ActualDollars(this PayrollOpportunityMetric pom) =>
+ typeof(PayrollOpportunityMetric)
+ .GetProperties(BindingFlags.Instance | BindingFlags.Public)
+ .Where(p => p.Name.StartsWith("ActualMonth") && p.Name.EndsWith("Dollars"))
+ .Select(dp => (decimal)dp.GetValue(pom, null));
+
+ public static IEnumerable CommittedDollars(this PayrollOpportunityMetric pom) =>
+ typeof(PayrollOpportunityMetric)
+ .GetProperties(BindingFlags.Instance | BindingFlags.Public)
+ .Where(p => p.Name.StartsWith("CommittedMonth") && p.Name.EndsWith("Dollars"))
+ .Select(dp => (decimal)dp.GetValue(pom, null));
+}
\ No newline at end of file
diff --git a/Calculate FactOpportunityMetrics YTD Rollups.linq b/Calculate FactOpportunityMetrics YTD Rollups.linq
new file mode 100644
index 0000000..b49009b
--- /dev/null
+++ b/Calculate FactOpportunityMetrics YTD Rollups.linq
@@ -0,0 +1,96 @@
+
+
+ 77b65bea-e766-4e3c-a1ed-c4c2534b6019
+ true
+ D0001-SQL-11.sdt.local
+ jazz dev master Prod
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+void Main()
+{
+ DimTimeClasses.Dump();
+
+ var factList = from fact in FactOpportunityMetrics.ToList()
+ join fm in DimFiscalMonths.ToList() on fact.FiscalMonthID equals fm.FiscalMonthID
+ join dtc in DimTimeClasses.ToList() on fact.TimeClassID equals dtc.TimeClassID
+ select new { fact, fm.SortOrder };
+
+ var updates =
+ (from f in factList //.Where(l => l.fact.TimeClassID != 5)
+ select new
+ {
+ f.fact,
+ AmountYTD = factList
+ .Where(l => l.fact.OpportunityGUID == f.fact.OpportunityGUID && l.fact.TimeClassID == f.fact.TimeClassID && l.fact.FiscalYearID == f.fact.FiscalYearID && l.SortOrder <= f.SortOrder)
+ .GroupBy(l => new { l.fact.OpportunityGUID, l.fact.TimeClassID, l.fact.FiscalYearID })
+ .Select(l => l.Sum(x => x.fact.Amount)).Single()
+ }).Where(r => r.AmountYTD != 0).OrderBy(r => r.fact.RowID).ToList();
+
+ foreach (var update in updates)
+ {
+ FactOpportunityMetrics.Where(fom => update.RowID == fom.RowID).ToList()
+ .ForEach(fact => fact.AmountYTD = update.AmountYTD);
+ FactOpportunityMetrics.Where(fom => update.RowID == fom.RowID).Dump();
+ }
+
+ SubmitChanges();
+ FactOpportunityMetrics.Where(fom => fom.AmountYTD != 0)
+ .Join(ViewOpportunity, f => f.OpportunityGUID, o => o.OpportunityGUID,
+ (f, o) => new { f.MetricName, f.TimeClassID, f.FiscalYearID, f.FiscalMonthID, f.Amount, f.AmountYTD, o.Name, o.OpportunityType }).Dump();
+}
+
+
+// Define other methods and classes here
\ No newline at end of file
diff --git a/CaseType Analytics/CaseType Analysis.linq b/CaseType Analytics/CaseType Analysis.linq
new file mode 100644
index 0000000..10fbc55
--- /dev/null
+++ b/CaseType Analytics/CaseType Analysis.linq
@@ -0,0 +1,193 @@
+
+
+ 77b65bea-e766-4e3c-a1ed-c4c2534b6019
+ true
+ D0001-SQL-11.sdt.local
+ jazz dev master Prod
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+ System.ComponentModel
+
+
+void Main()
+{
+ var caseTypes = (from fpes in FactPatientEncounterSummaries
+ join ves in VariationEncounterSavings on fpes.EncounterID equals ves.EncounterID
+ join vo in VariationOpportunities on ves.OpportunityGUID equals vo.OpportunityGUID
+ join config in Configurations on vo.ConfigurationGUID equals config.ConfigurationGUID
+ join cte in CaseTypeEntities on vo.CaseTypeEntityID equals cte.CaseTypeEntityID
+ join dct in DimCaseTypes on cte.CaseTypeGUID equals dct.MemberGUID
+ join d in DimMSDRGs on fpes.ReportingDRGID equals d.MSDRGID into da
+ from e in da.DefaultIfEmpty()
+ join f in DimAPRDRGs on fpes.APDRGID equals f.APRDRGID into fa
+ from g in fa.DefaultIfEmpty()
+ join cpt in DimCPTs on fpes.PrimaryCPTID equals cpt.CPTID into cpta
+ from ca in cpta.DefaultIfEmpty()
+ where config.FiscalYearID == 2020
+ select new
+ {
+ vo.ConfigurationGUID,
+ config.FiscalYearID,
+ dct.CaseTypeId,
+ dct.Name,
+ CCMCCCategory = e.CCMCCCategory ?? "",
+ SOI = g.APRSOI ?? "",
+ ROM = g.APRROM ?? "",
+ CPTCode = ca.CPTCode ?? "",
+ CaseTypeConfig = JsonConvert.DeserializeObject(dct.CaseTypeConfigJSON)
+ })
+ .Distinct()
+ .Select(t => new
+ {
+ t.ConfigurationGUID,
+ t.FiscalYearID,
+ t.CaseTypeId,
+ t.Name,
+ t.CCMCCCategory,
+ t.SOI,
+ t.ROM,
+ t.CPTCode,
+ t.CaseTypeConfig.AgeCohortIDInclusions,
+ t.CaseTypeConfig.PhysicianIDExclusions,
+ t.CaseTypeConfig.StandardDeviationExcludedTypeEnum,
+ t.CaseTypeConfig.LengthOfStayThreshold,
+ t.CaseTypeConfig.SOIROMInclusions,
+ t.CaseTypeConfig.CCMCCCategories,
+ t.CaseTypeConfig.CPTCodes,
+ t.CaseTypeConfig.PatientTypeRollupIDInclusions,
+ t.CaseTypeConfig.PhysicianMinVolume
+ })
+ .OrderBy(t => t.Name);
+ caseTypes.Dump();
+}
+
+// Define other methods and classes here
+public const string CCMCCCATEGORY_CC = "CC";
+public const string CCMCCCATEGORY_MCC = "MCC";
+public const string CCMCCCATEGORY_WO = "W/O";
+public const string CCMCCCATEGORY_NA = "N/A";
+public const string CCMCCCATEGORY_CCMCC = "CC/MCC";
+
+
+public enum CCMCCCategoryTypes
+{
+ ///
+ /// No Category
+ ///
+ [Description("")]
+ None,
+ ///
+ /// Complication or Comorbidity
+ ///
+ [Description(CCMCCCATEGORY_CC)]
+ CC,
+ ///
+ /// Major Complication or Comorbidity
+ ///
+ [Description(CCMCCCATEGORY_MCC)]
+ MCC,
+ ///
+ /// Without Complication or Comorbidity OR Major Complication or Comorbidity
+ ///
+ [Description(CCMCCCATEGORY_WO)]
+ WO,
+ ///
+ /// Not Available
+ ///
+ [Description(CCMCCCATEGORY_NA)]
+ NA,
+ ///
+ /// Both Complication or Comorbidity AND Major Complication or Comorbidity
+ ///
+ [Description(CCMCCCATEGORY_CCMCC)]
+ CCMCC
+}
+
+public class SOIROMInclusion
+{
+ public string SOI { get; }
+ public string ROM { get; }
+
+ public SOIROMInclusion(string soi, string rom)
+ {
+ SOI = soi;
+ ROM = rom;
+ }
+}
+
+public class CaseTypeDRGConfiguration
+{
+ public int PhysicianMinVolume { get; set; }
+ public List AgeCohortIDInclusions { get; set; }
+ public List PhysicianIDExclusions { get; set; }
+ public int StandardDeviationExcludedTypeEnum { get; set; }
+ public int LengthOfStayThreshold { get; set; }
+ public List PatientTypeRollupIDInclusions { get; set; }
+ public List SOIROMInclusions { get; set; }
+ public HashSet CCMCCCategories { get; set; }
+ public HashSet CPTCodes { get; set; }
+
+ public CaseTypeDRGConfiguration()
+ {
+ PhysicianMinVolume = 0;
+ AgeCohortIDInclusions = new List();
+ PhysicianIDExclusions = new List();
+ PatientTypeRollupIDInclusions = new List();
+ StandardDeviationExcludedTypeEnum = 0;
+ LengthOfStayThreshold = 0;
+ CCMCCCategories = new HashSet();
+ CPTCodes = new HashSet();
+ }
+
+}
\ No newline at end of file
diff --git a/CaseType Analytics/CaseTypeDestination.linq b/CaseType Analytics/CaseTypeDestination.linq
new file mode 100644
index 0000000..de79a47
--- /dev/null
+++ b/CaseType Analytics/CaseTypeDestination.linq
@@ -0,0 +1,139 @@
+
+
+ 870a756b-af44-4db4-b004-58ff41318b3a
+ true
+ P9900-SQL-11.sdt.local
+ jazz tst GM DSS Share Training Master
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+private IEnumerable existing_versions;
+private IEnumerable existing_migrations;
+private IEnumerable existing_families;
+private IEnumerable existing_mappings;
+
+void Main()
+{
+ Step1();
+
+ existing_migrations.Dump();
+ existing_versions.Dump();
+ existing_families.Count().Dump();
+ existing_mappings.Count().Dump();
+ var documentFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(existing_migrations)}.json"), JsonConvert.SerializeObject(existing_migrations, Newtonsoft.Json.Formatting.Indented));
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(existing_versions)}.json"), JsonConvert.SerializeObject(existing_versions, Newtonsoft.Json.Formatting.Indented));
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(existing_families)}.json"), JsonConvert.SerializeObject(existing_families, Newtonsoft.Json.Formatting.Indented));
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(existing_mappings)}.json"), JsonConvert.SerializeObject(existing_mappings, Newtonsoft.Json.Formatting.Indented));
+}
+
+// Define other methods and classes here
+private void Step1()
+{
+ existing_migrations = from ml in MigrationLogs where ml.DateTimeStamp > new DateTime(2018, 11, 16) && ml.Name.Replace(" ", "").Contains("CaseType") orderby ml.DateTimeStamp descending select ml.Name;
+ existing_versions = from ctfv in CaseTypeFamilyVersions select new VersionInfo(ctfv.CaseTypeFamilyVersionID, ctfv.Name, ctfv.StartDate, ctfv.EndDate);
+ existing_families = from ctf in CaseTypeFamilies select new FamilyInfo(ctf.CaseTypeFamilyGlobalID, ctf.Name, ctf.CaseTypeFamilyID);
+ existing_mappings = (from ctfm in CaseTypeFamilyMappingICD10s
+ join family in CaseTypeFamilies on ctfm.CaseTypeFamilyID equals family.CaseTypeFamilyID
+ where ctfm.CaseTypeFamilyVersionID == 1
+ select new MappingInfo(family.CaseTypeFamilyGlobalID, ctfm.SkipICD, ctfm.ICD10Code, ctfm.MSDRGCode)).Distinct();
+}
+
+
+public class VersionInfo
+{
+ public int CaseTypeFamilyVersionId { get; set; }
+ public string Name { get; set; }
+ public DateTime StartDate { get; set; }
+ public DateTime EndDate { get; set; }
+
+ public VersionInfo(int id, string name, DateTime start, DateTime end)
+ {
+ CaseTypeFamilyVersionId = id;
+ Name = name;
+ StartDate = start;
+ EndDate = end;
+ }
+}
+
+public class FamilyInfo
+{
+ public int CaseTypeFamilyID { get; set; }
+ public string CaseTypeFamilyGlobalID { get; set; }
+ public string Name { get; set; }
+
+ public FamilyInfo(string caseTypeFamilyGlobalID, string name, int caseTypeFamilyID)
+ {
+ CaseTypeFamilyID = caseTypeFamilyID;
+ CaseTypeFamilyGlobalID = caseTypeFamilyGlobalID;
+ Name = name;
+ }
+}
+
+public class MappingInfo
+{
+ public string CaseTypeFamilyGlobalID { get; set; }
+ public bool SkipICD { get; set; }
+ public string ICD10Code { get; set; }
+ public string MSDRGCode { get; set; }
+
+ public MappingInfo(string caseTypeFamilyGlobalID, bool skipICD, string icd10Code, string msdrgCode)
+ {
+ CaseTypeFamilyGlobalID = caseTypeFamilyGlobalID;
+ SkipICD = skipICD;
+ ICD10Code = icd10Code;
+ MSDRGCode = msdrgCode;
+ }
+}
diff --git a/CaseType Analytics/CaseTypeFamily Create Corrections.linq b/CaseType Analytics/CaseTypeFamily Create Corrections.linq
new file mode 100644
index 0000000..3aa91dd
--- /dev/null
+++ b/CaseType Analytics/CaseTypeFamily Create Corrections.linq
@@ -0,0 +1,286 @@
+
+
+ 870a756b-af44-4db4-b004-58ff41318b3a
+ true
+ P9900-SQL-11.sdt.local
+ jazz tst GM non DSS Share Training Master
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+private IEnumerable correct_versions;
+private IEnumerable correct_migrations;
+private IEnumerable correct_families;
+private IEnumerable correct_mappings;
+private IEnumerable existing_versions;
+private IEnumerable existing_migrations;
+private IEnumerable existing_families;
+private IEnumerable existing_mappings;
+
+void Main()
+{
+ //var cts = Util.GetMyQueries().FirstOrDefault(u => u.FilePath.EndsWith("CaseTypeSource.linq"));
+ //var connStr = cts.GetConnectionInfo().DatabaseInfo.GetCxString();
+ Step1();
+ Step2();
+
+ var versions = (from cf in correct_versions
+ join ef in existing_versions on cf.CaseTypeFamilyVersionId equals ef.CaseTypeFamilyVersionId into cef
+ from ef in cef.DefaultIfEmpty()
+ select new { cf, ef }).ToList();
+ versions.Dump(nameof(versions));
+ var migrations = (from cf in correct_migrations
+ join ef in existing_migrations on cf equals ef into cef
+ from ef in cef.DefaultIfEmpty()
+ select new { cf, ef }).ToList();
+ var migrationDeletes = (from cf in existing_migrations
+ join ef in correct_migrations on cf equals ef into cef
+ from ef in cef.DefaultIfEmpty()
+ select new { cf, ef }).ToList();
+ var families = (from cf in correct_families
+ join ef in existing_families on cf.CaseTypeFamilyGlobalID equals ef.CaseTypeFamilyGlobalID into cef
+ from ef in cef.DefaultIfEmpty()
+ select new { cf, ef }).ToList();
+ var familyDeletes = (from cf in existing_families
+ join ef in correct_families on cf.CaseTypeFamilyGlobalID equals ef.CaseTypeFamilyGlobalID into cef
+ from ef in cef.DefaultIfEmpty()
+ select new { cf, ef }).ToList();
+ var mappings = (from cm in correct_mappings
+ join em in existing_mappings on new { cm.CaseTypeFamilyGlobalID, cm.SkipICD, cm.ICD10Code, cm.MSDRGCode }
+ equals new { em.CaseTypeFamilyGlobalID, em.SkipICD, em.ICD10Code, em.MSDRGCode } into cem
+ from em in cem.DefaultIfEmpty()
+ select new { cm, em }).ToList();
+ var mappingDeletes = (from cm in existing_mappings
+ join em in correct_mappings on new { cm.CaseTypeFamilyGlobalID, cm.SkipICD, cm.ICD10Code, cm.MSDRGCode }
+ equals new { em.CaseTypeFamilyGlobalID, em.SkipICD, em.ICD10Code, em.MSDRGCode } into cem
+ from em in cem.DefaultIfEmpty()
+ select new { cm, em }).ToList();
+
+ var documentFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ var sql = versions.Where(f => f.ef == null)
+ .Aggregate(@"", (x, y) => $@"{x}
+INSERT INTO [dss].[CaseTypeFamilyVersion] (CaseTypeFamilyVersionId, Name, StartDate, EndDate)
+SELECT '{y.cf.CaseTypeFamilyVersionId}', '{y.cf.Name}', '{y.cf.StartDate:G}', '{y.cf.EndDate:G}'
+WHERE NOT EXISTS (SELECT 1 FROM [dss].[CaseTypeFamilyVersion] WHERE CaseTypeFamilyVersionId = '{y.cf.CaseTypeFamilyVersionId}');
+");
+ if (File.Exists(Path.Combine(documentFolder, $"Case Type Family Corrections 1 ({this.Connection.Database}).sql")))
+ File.Delete(Path.Combine(documentFolder, $"Case Type Family Corrections 1 ({this.Connection.Database}).sql"));
+ if (!string.IsNullOrEmpty(sql.Trim()))
+ File.WriteAllText(Path.Combine(documentFolder, $"Case Type Family Corrections 1 ({this.Connection.Database}).sql"), sql);
+
+ sql = versions.Where(f => f.ef != null
+ && ((f.cf.Name != f.ef.Name
+ && f.cf.Name.Replace("And", "&") != f.ef.Name
+ && f.cf.Name.Replace(" And ", "&") != f.ef.Name)
+ || (f.cf.StartDate != f.ef.StartDate)
+ || (f.cf.EndDate != f.ef.EndDate)))
+ .Aggregate(@"", (x, y) => $@"{x}
+UPDATE [dss].[CaseTypeFamilyVersion]
+SET Name = '{y.cf.Name}', StartDate = '{y.cf.StartDate:G}', EndDate = '{y.cf.EndDate:G}'
+WHERE CaseTypeFamilyVersionId = '{y.cf.CaseTypeFamilyVersionId}'; -- current name = {y.ef.Name}
+");
+ if (File.Exists(Path.Combine(documentFolder, $"Case Type Family Corrections 2 ({this.Connection.Database}).sql")))
+ File.Delete(Path.Combine(documentFolder, $"Case Type Family Corrections 2 ({this.Connection.Database}).sql"));
+ if (!string.IsNullOrEmpty(sql.Trim()))
+ File.WriteAllText(Path.Combine(documentFolder, $"Case Type Family Corrections 2 ({this.Connection.Database}).sql"), sql);
+
+ sql = families.Where(f => f.ef == null)
+ .Aggregate(@"", (x, y) => $@"{x}
+INSERT INTO [dss].[CaseTypeFamily] (CaseTypeFamilyGlobalID, Name)
+SELECT '{y.cf.CaseTypeFamilyGlobalID}', '{y.cf.Name}'
+WHERE NOT EXISTS (SELECT 1 FROM [dss].[CaseTypeFamily] WHERE CaseTypeFamilyGlobalID = '{y.cf.CaseTypeFamilyGlobalID}');
+");
+ if (File.Exists(Path.Combine(documentFolder, $"Case Type Family Corrections 3 ({this.Connection.Database}).sql")))
+ File.Delete(Path.Combine(documentFolder, $"Case Type Family Corrections 3 ({this.Connection.Database}).sql"));
+ if (!string.IsNullOrEmpty(sql.Trim()))
+ File.WriteAllText(Path.Combine(documentFolder, $"Case Type Family Corrections 3 ({this.Connection.Database}).sql"), sql);
+
+ sql = families.Where(f => f.ef != null
+ && (f.cf.Name != f.ef.Name
+ && f.cf.Name.Replace("And", "&") != f.ef.Name
+ && f.cf.Name.Replace(" And ", "&") != f.ef.Name))
+ .Aggregate(@"", (x, y) => $@"{x}
+UPDATE [dss].[CaseTypeFamily]
+SET Name = '{y.cf.Name}'
+WHERE CaseTypeFamilyGlobalID = '{y.cf.CaseTypeFamilyGlobalID}'; -- current name = {y.ef.Name}
+");
+ if (File.Exists(Path.Combine(documentFolder, $"Case Type Family Corrections 4 ({this.Connection.Database}).sql")))
+ File.Delete(Path.Combine(documentFolder, $"Case Type Family Corrections 4 ({this.Connection.Database}).sql"));
+ if (!string.IsNullOrEmpty(sql.Trim()))
+ File.WriteAllText(Path.Combine(documentFolder, $"Case Type Family Corrections 4 ({this.Connection.Database}).sql"), sql);
+
+ var insert = sql = mappings.Where(f => f.em == null).Any()
+ ? @"INSERT INTO [dss].[CaseTypeFamilyMappingICD10] ([CaseTypeFamilyID], [SkipICD], [ICD10Code], [MSDRGCode], [CaseTypeFamilyVersionID])
+" : "";
+ var selects = mappings.Where(f => f.em == null)
+ .Select((y, idx) => new { query = $@"SELECT [CaseTypeFamilyID], {(y.cm.SkipICD ? 1 : 0)}, '{y.cm.ICD10Code}', '{y.cm.MSDRGCode}', 1 FROM [dss].[CaseTypeFamily] WHERE [CaseTypeFamilyGlobalID] = '{y.cm.CaseTypeFamilyGlobalID}'", idx })
+ .GroupBy(g => g.idx / 1000, (g, d) => d)
+ .Select(z => insert + string.Join("\r\nUNION ALL\r\n", z.Select(y => y.query)));
+ Enumerable.Range(0, 999).ToList()
+ .ForEach(y =>
+ {
+ if (File.Exists(Path.Combine(documentFolder, $"Case Type Family Corrections 3{y:000} ({this.Connection.Database}).sql")))
+ File.Delete(Path.Combine(documentFolder, $"Case Type Family Corrections 3{y:000} ({this.Connection.Database}).sql"));
+ });
+ selects.ForEach((x, y) => File.WriteAllText(Path.Combine(documentFolder, $"Case Type Family Corrections 3{y:000} ({this.Connection.Database}).sql"), x));
+
+ versions.Where(f => f.ef == null).Dump("missing versions");
+ migrations.Where(f => f.ef == null).Dump("missing migrations");
+ migrationDeletes.Where(f => f.ef == null).Dump("migrations to delete");
+ families.Where(f => f.ef == null).Dump("missing families");
+ families.Where(f => f.ef != null
+ && (f.cf.Name != f.ef.Name
+ && f.cf.Name.Replace("And", "&") != f.ef.Name
+ && f.cf.Name.Replace(" And ", "&") != f.ef.Name)).Dump("families to update");
+ familyDeletes.Where(f => f.ef == null).Dump("families to detele");
+ mappings.Where(f => f.em == null).Dump("missing mappings");
+ mappings.Where(f => f.em != null && (f.cm.SkipICD != f.em.SkipICD || f.cm.ICD10Code != f.em.ICD10Code || f.cm.MSDRGCode != f.em.MSDRGCode)).Dump("mappings to update");
+ mappingDeletes.Where(f => f.em == null).Dump("mappings to delete");
+
+}
+
+
+// Define other methods and classes here
+
+///
+/// Connect to P2680-SQL-03 - jazz prd Mercy Health 20160308.1
+///
+private void Step1(string connectionString)
+{
+ var currentConnection = this.Connection.ConnectionString;
+ this.Connection.ConnectionString = connectionString;
+ this.Connection.Dump();
+
+ correct_migrations = from ml in MigrationLogs
+ where ml.Name.Replace(" ", "").Contains("CaseType") //&& ml.DateTimeStamp > new DateTime(2018, 11, 16)
+ orderby ml.DateTimeStamp descending
+ select ml.Name;
+ correct_versions = from ctfv in CaseTypeFamilyVersions select new VersionInfo(ctfv.CaseTypeFamilyVersionID, ctfv.Name, ctfv.StartDate, ctfv.EndDate);
+ correct_families = from ctf in CaseTypeFamilies select new FamilyInfo(ctf.CaseTypeFamilyGlobalID, ctf.Name, ctf.CaseTypeFamilyID);
+ correct_mappings = (from ctfm in CaseTypeFamilyMappingICD10s
+ join family in CaseTypeFamilies on ctfm.CaseTypeFamilyID equals family.CaseTypeFamilyID
+ where ctfm.CaseTypeFamilyVersionID == 1
+ select new MappingInfo(family.CaseTypeFamilyGlobalID, ctfm.SkipICD, ctfm.ICD10Code, ctfm.MSDRGCode)).Distinct();
+
+ this.Connection.ConnectionString = currentConnection;
+}
+
+private void Step1()
+{
+ var documentFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ correct_migrations = JsonConvert.DeserializeObject>(File.ReadAllText(Path.Combine(documentFolder, $"{nameof(correct_migrations)}.json")));
+ correct_versions = JsonConvert.DeserializeObject>(File.ReadAllText(Path.Combine(documentFolder, $"{nameof(correct_versions)}.json")));
+ correct_families = JsonConvert.DeserializeObject>(File.ReadAllText(Path.Combine(documentFolder, $"{nameof(correct_families)}.json")));
+ correct_mappings = JsonConvert.DeserializeObject>(File.ReadAllText(Path.Combine(documentFolder, $"{nameof(correct_mappings)}.json")));
+}
+
+private void Step2()
+{
+ existing_migrations = from ml in MigrationLogs
+ where ml.Name.Replace(" ", "").Contains("CaseType") //&& ml.DateTimeStamp > new DateTime(2018, 11, 16)
+ orderby ml.DateTimeStamp
+ select ml.Name;
+ existing_versions = from ctfv in CaseTypeFamilyVersions select new VersionInfo(ctfv.CaseTypeFamilyVersionID, ctfv.Name, ctfv.StartDate, ctfv.EndDate);
+ existing_families = from ctf in CaseTypeFamilies select new FamilyInfo(ctf.CaseTypeFamilyGlobalID, ctf.Name, ctf.CaseTypeFamilyID);
+ existing_mappings = (from ctfm in CaseTypeFamilyMappingICD10s
+ join family in CaseTypeFamilies on ctfm.CaseTypeFamilyID equals family.CaseTypeFamilyID
+ where ctfm.CaseTypeFamilyVersionID == 1
+ select new MappingInfo(family.CaseTypeFamilyGlobalID, ctfm.SkipICD, ctfm.ICD10Code, ctfm.MSDRGCode)).Distinct();
+}
+
+public class VersionInfo
+{
+ public int CaseTypeFamilyVersionId { get; set; }
+ public string Name { get; set; }
+ public DateTime StartDate { get; set; }
+ public DateTime EndDate { get; set; }
+
+ public VersionInfo(int id, string name, DateTime start, DateTime end)
+ {
+ CaseTypeFamilyVersionId = id;
+ Name = name;
+ StartDate = start;
+ EndDate = end;
+ }
+}
+
+public class FamilyInfo
+{
+ public int CaseTypeFamilyID { get; set; }
+ public string CaseTypeFamilyGlobalID { get; set; }
+ public string Name { get; set; }
+
+ public FamilyInfo(string caseTypeFamilyGlobalID, string name, int caseTypeFamilyID)
+ {
+ CaseTypeFamilyID = caseTypeFamilyID;
+ CaseTypeFamilyGlobalID = caseTypeFamilyGlobalID;
+ Name = name;
+ }
+}
+
+public class MappingInfo
+{
+ public string CaseTypeFamilyGlobalID { get; set; }
+ public bool SkipICD { get; set; }
+ public string ICD10Code { get; set; }
+ public string MSDRGCode { get; set; }
+
+ public MappingInfo(string caseTypeFamilyGlobalID, bool skipICD, string icd10Code, string msdrgCode)
+ {
+ CaseTypeFamilyGlobalID = caseTypeFamilyGlobalID;
+ SkipICD = skipICD;
+ ICD10Code = icd10Code;
+ MSDRGCode = msdrgCode;
+ }
+}
\ No newline at end of file
diff --git a/CaseType Analytics/CaseTypeFamily Run Corrections.linq b/CaseType Analytics/CaseTypeFamily Run Corrections.linq
new file mode 100644
index 0000000..42bf361
--- /dev/null
+++ b/CaseType Analytics/CaseTypeFamily Run Corrections.linq
@@ -0,0 +1,79 @@
+
+
+ 870a756b-af44-4db4-b004-58ff41318b3a
+ true
+ P9900-SQL-11.sdt.local
+ jazz tst GM non DSS Share Training Master
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+void Main()
+{
+ var documentFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ var files = Directory.GetFiles(documentFolder, "Case Type Family Corrections*.sql")
+ .Select(d => Path.GetFileName(d))
+ .OrderBy(d => d)
+ .ToList();
+ files.ForEach(f =>
+ {
+ "".Dump(f);
+ var query = File.ReadAllText(Path.Combine(documentFolder, f));
+ this.ExecuteCommand(query);
+ });
+
+
+}
+
+// Define other methods and classes here
diff --git a/CaseType Analytics/CaseTypeSource.linq b/CaseType Analytics/CaseTypeSource.linq
new file mode 100644
index 0000000..6439e51
--- /dev/null
+++ b/CaseType Analytics/CaseTypeSource.linq
@@ -0,0 +1,142 @@
+
+
+ 94a82e0d-b8c1-4789-96cc-f34a75ba3c45
+ true
+ P2980-SQL-03.sdt.local
+ jazz prd Mercy Health 20160308.1
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+private IEnumerable correct_versions;
+private IEnumerable correct_migrations;
+private IEnumerable correct_families;
+private IEnumerable correct_mappings;
+
+void Main()
+{
+ Step1();
+
+ correct_migrations.Dump();
+ correct_versions.Dump();
+ correct_families.Count().Dump();
+ correct_mappings.Count().Dump();
+ var documentFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(correct_migrations)}.json"), JsonConvert.SerializeObject(correct_migrations, Newtonsoft.Json.Formatting.Indented));
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(correct_versions)}.json"), JsonConvert.SerializeObject(correct_versions, Newtonsoft.Json.Formatting.Indented));
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(correct_families)}.json"), JsonConvert.SerializeObject(correct_families, Newtonsoft.Json.Formatting.Indented));
+ File.WriteAllText(Path.Combine(documentFolder, $"{nameof(correct_mappings)}.json"), JsonConvert.SerializeObject(correct_mappings, Newtonsoft.Json.Formatting.Indented));
+}
+
+// Define other methods and classes here
+private void Step1()
+{
+ correct_migrations = from ml in MigrationLogs
+ where ml.Name.Replace(" ", "").Contains("CaseType") //&& ml.DateTimeStamp > new DateTime(2018, 11, 16)
+ orderby ml.DateTimeStamp descending
+ select ml.Name;
+ correct_versions = from ctfv in CaseTypeFamilyVersions select new VersionInfo(ctfv.CaseTypeFamilyVersionID, ctfv.Name, ctfv.StartDate, ctfv.EndDate);
+ correct_families = from ctf in CaseTypeFamilies select new FamilyInfo(ctf.CaseTypeFamilyGlobalID, ctf.Name, ctf.CaseTypeFamilyID);
+ correct_mappings = (from ctfm in CaseTypeFamilyMappingICD10s
+ join family in CaseTypeFamilies on ctfm.CaseTypeFamilyID equals family.CaseTypeFamilyID
+ where ctfm.CaseTypeFamilyVersionID == 1
+ select new MappingInfo(family.CaseTypeFamilyGlobalID, ctfm.SkipICD, ctfm.ICD10Code, ctfm.MSDRGCode)).Distinct();
+}
+
+
+public class VersionInfo
+{
+ public int CaseTypeFamilyVersionId { get; set; }
+ public string Name { get; set; }
+ public DateTime StartDate { get; set; }
+ public DateTime EndDate { get; set; }
+
+ public VersionInfo(int id, string name, DateTime start, DateTime end)
+ {
+ CaseTypeFamilyVersionId = id;
+ Name = name;
+ StartDate = start;
+ EndDate = end;
+ }
+}
+
+public class FamilyInfo
+{
+ public int CaseTypeFamilyID { get; set; }
+ public string CaseTypeFamilyGlobalID { get; set; }
+ public string Name { get; set; }
+
+ public FamilyInfo(string caseTypeFamilyGlobalID, string name, int caseTypeFamilyID)
+ {
+ CaseTypeFamilyID = caseTypeFamilyID;
+ CaseTypeFamilyGlobalID = caseTypeFamilyGlobalID;
+ Name = name;
+ }
+}
+
+public class MappingInfo
+{
+ public string CaseTypeFamilyGlobalID { get; set; }
+ public bool SkipICD { get; set; }
+ public string ICD10Code { get; set; }
+ public string MSDRGCode { get; set; }
+
+ public MappingInfo(string caseTypeFamilyGlobalID, bool skipICD, string icd10Code, string msdrgCode)
+ {
+ CaseTypeFamilyGlobalID = caseTypeFamilyGlobalID;
+ SkipICD = skipICD;
+ ICD10Code = icd10Code;
+ MSDRGCode = msdrgCode;
+ }
+}
diff --git a/CaseType Analytics/Cleanup CaseTypeFamilyMappingICD10 SkipICD.linq b/CaseType Analytics/Cleanup CaseTypeFamilyMappingICD10 SkipICD.linq
new file mode 100644
index 0000000..2e8a5c6
--- /dev/null
+++ b/CaseType Analytics/Cleanup CaseTypeFamilyMappingICD10 SkipICD.linq
@@ -0,0 +1,788 @@
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.ComponentModel.Composition
+ System.ComponentModel.Composition.Hosting
+ System.ComponentModel.Composition.Primitives
+ System.ComponentModel.Composition.ReflectionModel
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ System.Net.Http
+ System.Net.Http.Headers
+ System.Numerics
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+private string text = @"1 558 M-296
+1 987 M-345
+1 895 M-16
+1 670 M-304
+1 445 M-98
+1 599 A-19
+1 505 M-125
+1 033 M-322
+1 247 M-229
+1 881 M-90
+1 294 M-100
+1 605 M-305
+1 208 M-367
+1 163 M-177
+1 248 M-230
+1 182 M-262
+1 637 A-6
+1 287 M-337
+1 815 M-264
+1 344 M-194
+1 387 A-13
+1 281 M-5
+1 985 M-249
+1 923 M-354
+1 896 M-17
+1 920 M-338
+1 230 A-21
+1 975 M-142
+1 504 M-125
+1 754 M-187
+1 950 M-13
+1 263 M-321
+1 579 M-362
+1 034 M-231
+1 595 A-18
+1 574 M-277
+1 472 M-61
+1 258 M-56
+1 776 M-245
+1 200 M-241
+1 336 A-24
+1 603 M-58
+1 334 M-253
+1 729 M-217
+1 816 M-264
+1 158 M-89
+1 485 M-163
+1 310 M-328
+1 555 M-274
+1 600 M-204
+1 661 M-162
+1 849 A-26
+1 939 M-346
+1 389 M-131
+1 187 M-239
+1 410 M-283
+1 712 M-297
+1 333 M-253
+1 186 M-239
+1 510 M-222
+1 343 M-29
+1 865 A-32
+1 790 M-116
+1 183 M-178
+1 501 M-280
+1 578 M-276
+1 809 M-182
+1 781 M-25
+1 750 M-214
+1 150 M-108
+1 350 M-152
+1 770 M-281
+1 335 A-24
+1 453 M-27
+1 053 M-288
+1 474 M-21
+1 424 M-353
+1 709 M-228
+1 178 M-261
+1 561 M-72
+1 100 M-270
+1 710 M-228
+1 556 M-274
+1 416 M-65
+1 123 M-201
+1 935 M-203
+1 516 M-357
+1 355 M-140
+1 215 M-137
+1 189 M-251
+1 094 M-34
+1 064 M-59
+1 685 M-8
+1 617 M-22
+1 759 A-9
+1 464 M-323
+1 725 M-36
+1 664 M-193
+1 789 M-344
+1 167 M-361
+1 292 A-12
+1 800 A-29
+1 509 M-30
+1 668 M-304
+1 069 A-31
+1 594 A-27
+1 882 M-202
+1 663 M-193
+1 314 A-22
+1 767 M-318
+1 489 M-164
+1 871 M-273
+1 688 M-161
+1 959 M-359
+1 667 M-248
+1 455 M-27
+1 675 M-355
+1 006 M-169
+1 155 M-213
+1 228 A-21
+1 059 M-88
+1 760 M-118
+1 843 M-220
+1 903 M-111
+1 070 M-60
+1 031 M-322
+1 495 M-109
+1 779 M-1
+1 928 M-129
+1 179 M-261
+1 222 M-55
+1 371 M-180
+1 381 M-70
+1 949 M-13
+1 298 M-52
+1 792 M-247
+1 285 M-6
+1 308 M-328
+1 221 M-285
+1 657 M-159
+1 264 M-349
+1 028 A-28
+1 639 A-6
+1 511 M-222
+1 500 M-280
+1 695 M-158
+1 180 M-262
+1 176 A-25
+1 674 M-355
+1 037 M-115
+1 945 M-105
+1 597 A-19
+1 478 M-41
+1 841 M-172
+1 869 M-150
+1 306 M-75
+1 948 M-368
+1 570 M-329
+1 654 A-15
+1 138 M-196
+1 908 M-358
+1 434 M-66
+1 538 M-291
+1 559 M-72
+1 965 M-356
+1 202 M-48
+1 557 M-296
+1 689 M-160
+1 244 M-234
+1 446 M-98
+1 101 M-270
+1 723 M-189
+1 225 M-54
+1 835 M-4
+1 549 M-272
+1 262 M-57
+1 964 M-356
+1 956 M-167
+1 376 A-7
+1 437 M-188
+1 135 M-275
+1 352 M-152
+1 984 M-249
+1 226 M-53
+1 283 M-6
+1 218 M-284
+1 370 A-16
+1 540 M-209
+1 191 M-77
+1 534 M-120
+1 602 M-58
+1 982 M-114
+1 148 M-102
+1 838 M-62
+1 007 M-171
+1 293 A-12
+1 097 M-287
+1 280 M-5
+1 498 M-110
+1 746 M-317
+1 830 M-199
+1 272 M-334
+1 067 M-205
+1 458 M-290
+1 078 M-146
+1 147 M-102
+1 345 M-194
+1 071 M-60
+1 295 M-100
+1 096 M-34
+1 235 M-49
+1 385 A-13
+1 624 M-279
+1 499 M-110
+1 922 M-354
+1 234 M-50
+1 423 M-353
+1 989 M-345
+1 715 M-186
+1 765 M-84
+1 934 M-128
+1 550 M-272
+1 137 M-196
+1 918 M-242
+1 056 M-86
+1 958 M-359
+1 868 M-150
+1 207 M-366
+1 250 M-232
+1 442 M-99
+1 826 M-342
+1 671 M-311
+1 062 M-293
+1 201 M-241
+1 165 M-177
+1 257 M-371
+1 441 M-99
+1 565 M-198
+1 421 M-139
+1 886 M-35
+1 625 M-298
+1 085 M-306
+1 354 M-140
+1 074 M-80
+1 038 M-115
+1 113 A-20
+1 791 M-246
+1 393 M-210
+1 660 M-162
+1 857 M-244
+1 904 M-278
+1 630 M-351
+1 940 M-346
+1 197 M-153
+1 241 M-282
+1 273 M-333
+1 330 M-175
+1 390 M-131
+1 195 M-240
+1 456 M-290
+1 814 M-264
+1 713 M-308
+1 866 A-32
+1 553 M-43
+1 010 A-23
+1 747 M-317
+1 804 M-360
+1 125 M-211
+1 473 M-61
+1 700 M-216
+1 755 M-187
+1 341 M-29
+1 933 M-113
+1 340 M-28
+1 496 M-109
+1 023 M-339
+1 289 M-7
+1 239 M-282
+1 963 M-356
+1 149 M-101
+1 159 M-89
+1 618 M-22
+1 515 M-357
+1 309 M-328
+1 193 M-240
+1 444 M-98
+1 242 M-234
+1 076 A-33
+1 577 M-276
+1 432 M-66
+1 029 A-28
+1 032 M-322
+1 691 M-313
+1 300 M-233
+1 016 M-32
+1 408 M-283
+1 435 M-188
+1 622 M-279
+1 870 M-271
+1 249 M-230
+1 502 M-280
+1 388 M-131
+1 662 M-193
+1 757 A-9
+1 828 M-342
+1 282 M-5
+1 604 M-305
+1 854 M-341
+1 573 M-277
+1 793 M-127
+1 554 M-43
+1 699 M-216
+1 058 M-88
+1 008 M-225
+1 339 M-28
+1 902 M-111
+1 223 M-55
+1 542 M-227
+1 115 M-286
+1 592 A-27
+1 269 M-332
+1 316 A-22
+1 846 M-63
+1 231 M-51
+1 768 M-319
+1 707 A-17
+1 665 M-248
+1 268 M-332
+1 883 M-235
+1 483 M-183
+1 856 M-244
+1 497 M-109
+1 134 M-350
+1 955 A-5
+1 642 M-76
+1 332 M-253
+1 181 M-262
+1 129 M-181
+1 976 M-142
+1 947 M-368
+1 139 M-269
+1 151 M-108
+1 718 M-218
+1 842 M-172
+1 440 M-97
+1 052 M-288
+1 040 M-363
+1 156 M-213
+1 229 A-21
+1 544 M-227
+1 847 M-63
+1 844 M-220
+1 382 M-70
+1 862 M-243
+1 077 M-146
+1 641 M-207
+1 572 M-329
+1 780 A-8
+1 744 M-85
+1 658 M-159
+1 927 M-112
+1 820 M-173
+1 216 M-284
+1 643 M-106
+1 166 M-361
+1 290 M-7
+1 233 M-50
+1 855 M-341
+1 083 M-307
+1 824 M-174
+1 411 M-64
+1 696 M-158
+1 304 A-128
+1 409 M-283
+1 055 M-200
+1 102 M-136
+1 655 A-15
+1 378 M-130
+1 520 M-335
+1 666 M-248
+1 687 M-161
+1 693 M-312
+1 079 M-146
+1 099 M-287
+1 307 M-75
+1 914 M-370
+1 327 M-369
+1 539 M-209
+1 722 M-189
+1 546 A-4
+1 133 M-350
+1 834 M-4
+1 969 M-340
+1 368 A-16
+1 375 A-7
+1 894 M-18
+1 297 M-52
+1 457 M-290
+1 717 M-218
+1 004 M-301
+1 383 M-309
+1 303 M-31
+1 065 M-59
+1 724 M-189
+1 728 M-151
+1 801 A-29
+1 255 M-371
+1 014 M-19
+1 672 M-311
+1 880 M-2
+1 291 A-12
+1 863 M-243
+1 232 M-51
+1 017 M-32
+1 256 M-371
+1 130 M-181
+1 063 M-293
+1 417 M-166
+1 296 M-52
+1 748 M-119
+1 475 M-21
+1 438 M-97
+1 734 M-252
+1 745 M-85
+1 970 M-340
+1 545 A-4
+1 593 A-27
+1 566 M-198
+1 425 M-353
+1 897 M-17
+1 487 M-163
+1 974 M-142
+1 627 M-298
+1 560 M-72
+1 562 M-197
+1 575 M-277
+1 177 M-261
+1 068 M-205
+1 271 M-334
+1 337 A-24
+1 782 M-26
+1 198 M-153
+1 203 M-48
+1 629 M-351
+1 199 M-241
+1 486 M-163
+1 714 M-308
+1 095 M-34
+1 623 M-279
+1 087 M-306
+1 917 M-242
+1 876 M-347
+1 716 M-186
+1 227 M-53
+1 380 M-70
+1 988 M-345
+1 517 M-357
+1 188 M-239
+1 152 M-223
+1 374 A-7
+1 284 M-6
+1 506 M-185
+1 711 M-297
+1 082 M-307
+1 802 M-360
+1 116 M-157
+1 795 M-206
+1 184 M-178
+1 395 M-210
+1 420 M-139
+1 073 M-80
+1 628 M-351
+1 921 M-338
+1 794 M-343
+1 114 A-20
+1 606 M-195
+1 286 M-337
+1 596 A-18
+1 035 M-231
+1 260 M-57
+1 415 M-65
+1 887 M-219
+1 471 M-61
+1 829 M-199
+1 645 M-106
+1 217 M-284
+1 146 M-102
+1 346 M-194
+1 758 A-9
+1 708 A-17
+1 827 M-342
+1 192 M-77
+1 351 M-152
+1 329 M-175
+1 205 M-221
+1 338 M-28
+1 541 M-209
+1 245 M-14
+1 749 M-214
+1 463 M-323
+1 086 M-306
+1 164 M-177
+1 769 M-364
+1 342 M-29
+1 601 M-204
+1 808 M-182
+1 386 A-13
+1 204 M-263
+1 810 M-182
+1 243 M-234
+1 454 M-27
+1 259 M-56
+1 837 M-62
+1 117 M-157
+1 433 M-66
+1 288 M-7
+1 813 M-68
+1 075 A-33
+1 576 M-276
+1 885 M-250
+1 692 M-313
+1 981 M-114
+1 224 M-54
+1 652 A-14
+1 261 M-57
+1 512 M-222
+1 372 M-180
+1 799 A-29
+1 686 M-161
+1 190 M-77
+1 638 A-6
+1 042 M-363
+1 465 M-323
+1 313 A-3
+1 414 M-65
+1 024 M-339
+1 598 A-19
+1 246 M-229
+1 519 M-335
+1 236 M-49
+1 547 A-4
+1 543 M-227
+1 946 M-105
+1 777 M-104
+1 419 M-166
+1 477 M-41
+1 840 M-172
+1 533 M-120
+1 659 M-162
+1 270 M-334
+1 872 M-273
+1 864 A-10
+1 154 M-213
+1 479 M-41
+1 909 M-358
+1 823 M-174
+1 503 M-125
+1 194 M-240
+1 735 M-252
+1 951 M-352
+1 030 A-28
+1 583 M-190
+1 656 M-159
+1 418 M-166
+1 690 M-160
+1 379 M-130
+1 326 M-369
+1 929 M-129
+1 518 M-335
+1 311 M-24
+1 157 M-89
+1 436 M-188
+1 041 M-363
+1 673 M-355
+1 582 M-190
+1 413 M-64
+1 853 M-341
+1 756 M-187
+1 124 M-211
+1 168 M-361
+1 901 M-111
+1 089 M-74
+1 581 M-362
+1 036 M-231
+1 775 M-327
+1 373 M-180
+1 913 M-370
+1 669 M-304
+1 301 M-233
+1 122 A-1
+1 312 M-294
+1 653 A-15
+1 315 A-22
+1 571 M-329
+1 039 M-115
+1 697 M-310
+1 369 A-16
+1 858 M-244
+1 551 M-192
+1 412 M-64
+1 265 M-15
+1 061 M-293
+1 084 M-307
+1 825 M-174
+1 088 M-74
+1 727 M-151
+1 240 M-282
+1 443 M-99
+1 054 M-200
+1 778 A-30
+1 730 M-217
+1 836 M-4
+1 185 M-178
+1 072 M-60
+1 220 M-285
+1 377 M-130
+1 175 A-25
+1 121 A-1
+1 353 M-140
+1 057 M-86
+1 867 M-150
+1 919 M-338
+1 274 M-333
+1 726 M-36
+1 644 M-106
+1 537 M-291
+1 552 M-192
+1 983 M-114
+1 328 M-369
+1 821 M-173
+1 564 M-198
+1 626 M-298
+1 098 M-287
+1 219 M-285
+1 060 M-88
+1 394 M-210
+1 384 M-309
+1 822 M-173
+1 136 M-275
+1 607 M-195
+1 153 M-223
+1 905 M-278
+1 616 M-22
+1 331 M-175
+1 066 M-59
+1 580 M-362
+1 907 M-358
+1 196 M-153
+1 476 M-21
+1 941 M-346
+1 548 M-272
+1 698 M-216
+1 439 M-97
+1 206 M-221
+1 916 A-2
+1 305 A-128
+1 803 M-360
+1 103 M-136
+1 251 M-232
+1 766 M-84
+1 915 A-2
+1 299 M-233
+1 563 M-197
+1 848 M-63
+1 986 M-249
+1 694 M-312
+1 957 M-359
+1 977 M-143
+1 845 M-220
+1 090 M-74
+1 488 M-164
+1 302 M-31
+1 839 M-62
+1 422 M-139
+1 761 M-118
+1 640 M-207
+1 774 M-330
+1 0 783 M-412
+1 0 784 M-412
+1 0 785 M-412
+1 0 786 M-413
+1 0 787 M-413
+1 0 788 M-413
+1 0 805 M-414
+1 0 806 M-414
+1 0 807 M-414
+1 0 817 M-415
+1 0 818 M-415
+1 0 819 M-415
+1 0 831 M-416
+1 0 832 M-416
+1 0 833 M-416
+1 0 796 M-318
+1 0 797 M-318
+1 0 798 M-318";
+
+void Main()
+{
+ var mappings = text.Replace("\r\n", "\r").Split('\r')
+ .Where(r => !string.IsNullOrEmpty(r) && r.Split('\t').Length == 4) // There must be exactly 4 columns in each row of data
+ .Select(x =>
+ {
+ var column = x.Split('\t');
+ return new CaseTypeFamilyMapping(column[0], column[1], column[2], column[3], 0);
+ });
+ mappings.Where(m => m != null).OrderBy(m => m.SkipICD).ThenBy(m => m.ICD10Code).ThenBy(m => m.MSDRGCode).ThenBy(m => m.GlobalID).Dump();
+}
+
+public class CaseTypeFamilyMapping
+{
+ public bool SkipICD { get; set; }
+ public string ICD10Code { get; set; }
+ public string MSDRGCode { get; set; }
+ public string GlobalID { get; set; }
+ public int CaseTypeFamilyId { get; set; }
+
+ public CaseTypeFamilyMapping(string skipICD, string icd10Code, string msdrgCode, string globalID, int caseTypeFamilyId)
+ {
+ if (!bool.TryParse(skipICD, out bool skipped)) skipped = false;
+ SkipICD = (skipICD == "1");
+ ICD10Code = icd10Code;
+ MSDRGCode = msdrgCode;
+ GlobalID = globalID;
+ //CaseTypeFamilyId = caseTypeFamilyId;
+ }
+
+}
diff --git a/CaseType Analytics/Cleanup CaseTypeFamilyMappingICD10 table.linq b/CaseType Analytics/Cleanup CaseTypeFamilyMappingICD10 table.linq
new file mode 100644
index 0000000..6b64b51
--- /dev/null
+++ b/CaseType Analytics/Cleanup CaseTypeFamilyMappingICD10 table.linq
@@ -0,0 +1,134 @@
+
+
+ 77b65bea-e766-4e3c-a1ed-c4c2534b6019
+ true
+ D0001-SQL-01.sdt.local
+ jazz dev master
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.ComponentModel.Composition
+ System.ComponentModel.Composition.Hosting
+ System.ComponentModel.Composition.Primitives
+ System.ComponentModel.Composition.ReflectionModel
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ System.Net.Http
+ System.Net.Http.Headers
+ System.Numerics
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+var grps = CaseTypeFamilyMappingICD10s
+.Where(ctf => ctf.CaseTypeFamilyVersionID == 2)
+.GroupBy(ctf => new { ctf.CaseTypeFamilyID, ctf.ICD10Code })
+.OrderBy(grp => grp.Key.CaseTypeFamilyID)
+.ThenBy(grp => grp.Key.ICD10Code)
+.Select(grp => new { grp.Key.CaseTypeFamilyID, grp.Key.ICD10Code, count = grp.Count() });
+
+var grpBreak = 100000;
+var pageSize = 10000;
+foreach (var grp in grps)
+{
+ grp.Dump();
+ if (grp.count > grpBreak)
+ {
+ var subgrps = CaseTypeFamilyMappingICD10s
+ .Where(ctf => ctf.CaseTypeFamilyVersionID == 2)
+ .GroupBy(ctf => new { ctf.CaseTypeFamilyID, ctf.ICD10Code, ctf.MSDRGCode })
+ .OrderBy(subgrp => subgrp.Key.CaseTypeFamilyID)
+ .ThenBy(subgrp => subgrp.Key.ICD10Code)
+ .ThenBy(subgrp => subgrp.Key.MSDRGCode)
+ .Select(subgrp => new { subgrp.Key.CaseTypeFamilyID, subgrp.Key.ICD10Code, subgrp.Key.MSDRGCode, count = subgrp.Count() });
+
+ foreach (var subgrp in subgrps)
+ {
+ subgrp.Dump();
+ var subgrpremove = from mapping in CaseTypeFamilyMappingICD10s
+ where mapping.CaseTypeFamilyID == subgrp.CaseTypeFamilyID
+ && mapping.ICD10Code == subgrp.ICD10Code
+ && mapping.MSDRGCode == subgrp.MSDRGCode
+ && mapping.CaseTypeFamilyVersionID == 2
+ select mapping;
+
+ if (subgrpremove.Any())
+ {
+ var pages = ((subgrp.count + (pageSize - 1)) / pageSize);
+ Enumerable.Range(0, pages).ToList()
+ .ForEach(page =>
+ {
+ $"{(page + 1)} of {pages}".Dump();
+ var workSet = subgrpremove.Skip(page * pageSize).Take(pageSize).ToList();
+ CaseTypeFamilyMappingICD10s.DeleteAllOnSubmit(workSet);
+ SubmitChanges();
+ });
+ }
+ }
+ continue;
+ }
+ var remove = from mapping in CaseTypeFamilyMappingICD10s
+ where mapping.CaseTypeFamilyID == grp.CaseTypeFamilyID
+ && mapping.ICD10Code == grp.ICD10Code
+ && mapping.CaseTypeFamilyVersionID == 2
+ select mapping;
+
+ if (remove.Any())
+ {
+ var pages = ((grp.count + (pageSize - 1)) / pageSize);
+ Enumerable.Range(0, pages).ToList()
+ .ForEach(page =>
+ {
+ $"{(page + 1)} of {pages}".Dump();
+ var workSet = remove.Skip(page * pageSize).Take(pageSize).ToList();
+ CaseTypeFamilyMappingICD10s.DeleteAllOnSubmit(workSet);
+ SubmitChanges();
+ });
+ }
+}
\ No newline at end of file
diff --git a/Create CCI StoreProc Unit Tests.linq b/Create CCI StoreProc Unit Tests.linq
new file mode 100644
index 0000000..d752e28
--- /dev/null
+++ b/Create CCI StoreProc Unit Tests.linq
@@ -0,0 +1,107 @@
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+var routines = @"procCleanupOpportunities
+procDeleteAllData
+procDeleteDimensionData
+procEpicADTInitializeDepartmentPatientCensus
+procInsertDimensionDefaults
+procOptimizationRebuildIndexesDimensions
+procPatientCensusDiscardIncorrectEntries
+procPatientEncounterSummaryUpdateCaseTypeId
+procPopulateCustomOpportunitySavings
+procPopulateDepartmentPatientCensus
+procPopulateDepartmentPatientCensusFromCerner
+procPopulateDepartmentPatientCensusFromMeditech
+procPopulateDepartmentPatientCensusFromStarADT
+procPopulateDepartmentPatientDailyCensus
+procPopulatePhysicianQualityMetrics
+procSampleCaseTypeFamilyMetricsAll
+procSampleChargeCodeConfigs
+procSampleMSDRGCaseTypeFamilyMetrics
+procSampleNursingDepartments
+procSampleNursingMonthlyVolume
+procSampleUNSPSCRollup
+procUpdateDimInitiative
+procUpdateDimOpportunity
+procUpdateFactOpportunityMetric
+procUpdateFactOpportunitySavings".Replace("\r\n", "\r").Split('\r');
+var bools = new[] { true }; //, false };
+var groups = new[] { 2, 3 };
+var variations = (from b in bools
+ from g in groups
+ from r in routines
+ select new { b = b && g != 1, g, r, q = g == 1 ? "NoQuery" : g == 2 ? "DataSet" : g == 3 ? "Datatable" : "Scalar" })
+ .Distinct()
+ .Where(v => v.r != "procPopulateCustomOpportunitySavings")
+ .OrderBy(o => o.q)
+ .ThenBy(o => o.r)
+ .ThenByDescending(o => o.b).ToList();
+
+//variations.Dump();
+
+variations.ForEach(v => $@" [Test]
+ public void TestxCci{v.r}{v.g}_{v.q}()
+ {{
+ var contextMock = new Mock().As();
+
+ using (contextMock.InScope())
+ {{
+ {(v.b ? "var ts = (int)TimeSpan.FromMinutes(5).TotalSeconds;\r\n " : "")}Action act = () => {v.r}.Execute{v.q}({(v.b ? "Guid.NewGuid()" : "")});
+ act.Should().NotThrow();
+ }}
+
+ contextMock.VerifyStoredProc<{v.r}>({(v.b ? "TimeSpan.FromMinutes(5), " : "")}Times.Never());
+ }}
+".Dump());
\ No newline at end of file
diff --git a/Create CPT CaseTypeFamily entries.linq b/Create CPT CaseTypeFamily entries.linq
new file mode 100644
index 0000000..d69d265
--- /dev/null
+++ b/Create CPT CaseTypeFamily entries.linq
@@ -0,0 +1,171 @@
+
+
+ 77b65bea-e766-4e3c-a1ed-c4c2534b6019
+ true
+ D0001-SQL-11.sdt.local
+ jazz dev master Prod
+ true
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+
+
+var opcptcodefile = @"D:\Users\tlamb\Downloads\OP CTF_03232020.txt";
+var opcptcodelist = File.ReadAllLines(opcptcodefile);
+var opcptcodes = opcptcodelist.Skip(1).Select(o => new { CaseTypeFamily = o.Split('\t')[0], CPTCode = o.Split('\t')[1].Trim() });
+
+var newCaseTypeFamily = from op in opcptcodes
+ join ctf in CaseTypeFamilies on op.CaseTypeFamily equals ctf.Name into joined
+ from j in joined.DefaultIfEmpty()
+ where j == null
+ select op.CaseTypeFamily;
+
+var newCaseTypeFamilies =
+@"--Author: tlamb
+--Version: 2020.21
+--Forward
+update pes set pes.MSDRGCaseTypeFamilyID = 0, pes.APRDRGCaseTypeFamilyID = 0
+from [clientdss].[FactPatientEncounterSummary] pes
+INNER JOIN fw.DimPatientType pt on pt.PatientTypeID = pes.PatientTypeID
+INNER JOIN fw.DimPatientTypeRollup ptr on pt.PatientTypeRollupID = ptr.PatientTypeRollupID
+where ptr.Type <> 'Inpatient';
+GO
+DELETE FROM dss.CaseTypeFamily WHERE CaseTypeFamilyGlobalID LIKE 'O-%';
+GO
+DELETE FROM dss.CaseTypeFamilyMappingCPT;
+GO
+" +
+string.Join("\r\n", opcptcodes
+.Select(o => o.CaseTypeFamily)
+.Distinct().OrderBy(ctf => ctf)
+.Select((ctf, i) => new {i, value = $"\t( NEWID(), N'{ctf}', N'O-{(i + 1):0000}' )"})
+.GroupBy(ctf => (int)ctf.i / 100, (g, d) => string.Join(",\r\n", d.Select(v => v.value)))
+.Select(ctf => $"INSERT INTO dss.CaseTypeFamily ( CaseTypeFamilyGUID, Name, CaseTypeFamilyGlobalID )\r\nVALUES\r\n{ctf};\r\nGO")) +
+@"
+DECLARE @CaseTypeFamilyVersionID INT;
+SELECT @CaseTypeFamilyVersionID = CaseTypeFamilyVersionID FROM dss.CaseTypeFamilyVersion AS ctfv WHERE GETDATE() BETWEEN ctfv.StartDate AND ctfv.EndDate;
+" +
+string.Join("\r\n", opcptcodes
+.Select(o => $@"INSERT INTO dss.CaseTypeFamilyMappingCPT ( CaseTypeFamilyID, CPTCode, CaseTypeFamilyVersionID )
+SELECT CaseTypeFamilyID, '{o.CPTCode}', @CaseTypeFamilyVersionID
+FROM dss.CaseTypeFamily AS ctf WHERE ctf.Name = '{o.CaseTypeFamily}'")) + @"
+GO
+--Rollback
+update pes set pes.MSDRGCaseTypeFamilyID = 0, pes.APRDRGCaseTypeFamilyID = 0
+from [clientdss].[FactPatientEncounterSummary] pes
+INNER JOIN fw.DimPatientType pt on pt.PatientTypeID = pes.PatientTypeID
+INNER JOIN fw.DimPatientTypeRollup ptr on pt.PatientTypeRollupID = ptr.PatientTypeRollupID
+where ptr.Type <> 'Inpatient';
+GO
+DELETE FROM dss.CaseTypeFamily WHERE CaseTypeFamilyGlobalID LIKE 'O-%';
+GO
+DELETE FROM dss.CaseTypeFamilyMappingCPT;
+GO
+";
+File.WriteAllText(@"D:\Git\jazz\Migrations\CCI\2020-03-25-15-34 D-09502 OP CaseTypeFamily Definitions 2.sql", newCaseTypeFamilies);
+newCaseTypeFamilies.Dump(nameof(newCaseTypeFamilies));
+
+/*
+var dbResults = from ctfmc in CaseTypeFamilyMappingCPTs
+ join ctf in CaseTypeFamilies on ctfmc.CaseTypeFamilyID equals ctf.CaseTypeFamilyID
+ join ctfv in CaseTypeFamilyVersions on ctfmc.CaseTypeFamilyVersionID equals ctfv.CaseTypeFamilyVersionID
+ select new { ctfmc.CPTCode, ctf.CaseTypeFamilyID, ctf.Name };
+
+var missing = from op in opcptcodes
+ join db in dbResults on op.CPTCode equals db.CPTCode into joined
+ from j in joined.DefaultIfEmpty()
+ where j == null ||
+ (j != null && op.CaseTypeFamily != j.Name)
+ select new
+ {
+ op.CPTCode,
+ NewName = op.CaseTypeFamily,
+ OldCaseTypeFamilyID = j?.CaseTypeFamilyID ?? -1,
+ OldName = j?.Name ?? ""
+ };
+
+var updates = from m in missing
+ join ctf in CaseTypeFamilies on m.NewName equals ctf.Name into joined
+ from j in joined.DefaultIfEmpty()
+ select new
+ {
+ m.CPTCode,
+ m.NewName,
+ NewCaseTypeFamilyID = j?.CaseTypeFamilyID ?? -1,
+ m.OldCaseTypeFamilyID,
+ m.OldName
+ };
+
+updates
+.Where(u => u.NewCaseTypeFamilyID != -1)
+.OrderBy(u => u.NewCaseTypeFamilyID)
+.Dump(nameof(updates));
+
+updates
+.Where(u => u.NewCaseTypeFamilyID == -1)
+.Count().Dump("Count");
+
+updates
+.Where(u => u.NewCaseTypeFamilyID == -1)
+.OrderBy(u => u.NewCaseTypeFamilyID)
+.Dump("New Case Type Family");
+
+var oldCaseTypeFamilies = updates
+.Where(u => u.NewCaseTypeFamilyID != -1)
+.Select(u => u.NewName).Distinct().OrderBy(u => u);
+oldCaseTypeFamilies.Dump(nameof(oldCaseTypeFamilies));
+
+var newCaseTypeFamilies = updates
+.Where(u => u.NewCaseTypeFamilyID == -1)
+.Select(u => u.NewName).Distinct().OrderBy(u => u);
+newCaseTypeFamilies.Dump(nameof(newCaseTypeFamilies));
+*/
\ No newline at end of file
diff --git a/CrossDB Missing StarterSet Definitions.linq b/CrossDB Missing StarterSet Definitions.linq
new file mode 100644
index 0000000..6e01d1d
--- /dev/null
+++ b/CrossDB Missing StarterSet Definitions.linq
@@ -0,0 +1,527 @@
+
+
+ db640701-a1c5-4177-9f03-5152d093ffa7
+ true
+ D0011-sql-01.sdt.local
+ jazz tst StrataSphere 20191104.1
+ true
+
+ RestSharp
+ RestSharp
+ Newtonsoft.Json
+ System.Data.Common
+
+
+private string BaseUrl = "https://localhost:44325/api/v1/"; //"https://api-dev.sdt.local/starterset-api/api/v1/"; //"https://starterset-api.dev.k8s.sdt.local/api/v1/";
+private List TheGrade = new List();
+
+#region *** Enumerations ***
+
+public enum QueryRegions
+{
+ Production,
+ Training,
+ Oak,
+ Dev
+}
+
+#endregion
+
+#region *** Options ***
+
+public static QueryRegions queryRegion = QueryRegions.Dev;
+public static string crossDBQueryPath = @"D:\CrossDBQueries"; // This is the path to find the queries
+public static bool dumpOptions = false; // This flag will dumpt this set of options
+public static bool dumpSmcSql = false; // This flag will dump the smc sql to the result
+public static bool dumpDBList = false; // This flag will dump the databases to the result
+public static bool dumpQueries = false; // This flag will dump the queries to the result
+public static bool dumpDBExclusions = false; // This flag will dump the db and server exclusions
+public static bool dumpDBTargets = false; // This flag will dump the db and server targets
+public static bool dumpAppVersions = false; // This flag will dump the app versions used in the queryRegion
+public static bool dumpAppVersionTargets = false; // This flag will dump the app versions targets
+public static bool excludeExceptions = true;
+public static bool queryCompress = false;
+public static bool flatten = true; // This will flatten all of the results into a single list
+public static bool showStopWatch = false;
+public static bool noQueries = false; // This will stop the CrossDBQuery without running the queries
+
+#endregion
+
+public static Parms parms = new Parms
+{
+ name = "FY2020"
+};
+
+#region *** Database Selection ***
+
+public static string[] appVersions = { // This is a list of appVersions to filter for in the database list
+ //"2019.42"
+};
+
+public static string[] serverExclusions = { // This is a list of servers to exclude from the database list
+ @"paonsql19.sdt.local\instance1",
+ @"paonsql17.sdt.local\instance1",
+ @"p0555-sql-01.sdt.local\instance1",
+ "P0000-sql-01.sdt.local",
+ "P9900-SQL-03.sdt.local",
+ "P9900-sql-05.sdt.local"
+};
+
+public static string[] dbExclusions = { // This is a list of database physical names to exclude from the database list
+};
+public static string[] targetOrgPins = { // This is a list of org pins to target in the database list
+};
+public static string[] targetServers = { // This is a list of servers to target in the database list
+};
+public static string[] targetDBs = { // This is a list of database physicial names to target in the database list
+//"jazz tst Aultman 20200417.1"
+};
+
+#endregion *** Options ***
+
+#region *** SMC Settings and queries ***
+
+public static string smcSql => @"SELECT di.ServerName, di.DatabaseGUID, di.DatabaseName, di.PhysicalName, di.OrgPin, di.AppVersion, di.Description
+FROM [dbo].[viewDatabaseInfo] di
+WHERE 1=1"
++ (queryRegion == QueryRegions.Dev
+? @"
+ AND di.PhysicalName like 'jazz%'"
+: $@"
+ AND di.PhysicalName like 'jazz {(queryRegion != QueryRegions.Production ? "tst" : "prd")}%'
+ AND di.ServerName like 'p%'");
+public static string smcServer { get; set; }
+public static string smcDB { get; set; }
+
+#endregion
+
+#region *** Program variables and settings ***
+
+public static IOrderedEnumerable databases => GetDatabases();
+
+#endregion
+
+public void OptionsDump()
+{
+ var options = new
+ {
+ queryRegion,
+ crossDBQueryPath,
+ dumpOptions,
+ dumpSmcSql,
+ dumpDBList,
+ dumpQueries,
+ dumpDBExclusions,
+ dumpDBTargets,
+ dumpAppVersions,
+ dumpAppVersionTargets,
+ excludeExceptions,
+ queryCompress,
+ flatten,
+ showStopWatch,
+ noQueries
+ };
+ options.Dump(nameof(options));
+}
+
+public class Parms
+{
+ public string name { get; set; }
+}
+
+void Main()
+{
+ RestClient client = new RestClient();
+ var definitions = GetList(client, "Definitions");
+ var definitionTranslations = GetList(client, "DefinitionTranslations");
+
+ var work = definitions
+ .GroupBy(d => new
+ {
+ d.HierarchyGuid,
+ d.DimensionGuid,
+ d.AttributeGuid,
+ d.HierarchyId,
+ d.DimensionId,
+ d.AttributeId
+ }, (g, d) => new WorkDto
+ {
+ DefinitionGuids = d.Select(x => x.Id).ToList(),
+ HierarchyGuid = g.HierarchyGuid,
+ DimensionGuid = g.DimensionGuid,
+ AttributeGuid = g.AttributeGuid,
+ HierarchyId = g.HierarchyId,
+ DimensionId = g.DimensionId,
+ AttributeId = g.AttributeId,
+ Name = g.AttributeId == "a177cc88-e329-44e0-9063-2d9b59af51b2"
+ ? "Department"
+ : g.AttributeId == "f23654b3-149f-490a-a366-fca35f57d66a"
+ ? "EntityID"
+ : g.AttributeId == "MRDEPTENTITY"
+ ? "Entity"
+ : string.Empty
+ })
+ .Distinct()
+ .OrderBy(d => d.DimensionId)
+ .ThenBy(d => d.AttributeId)
+ .ToList();
+
+ DoTheDumping();
+
+ databases
+ //.Where(d => d.DatabaseName == "Aultman")
+ .OrderBy(d => d.DatabaseName)
+ .ThenBy(d => d.OrgPin)
+ .ThenBy(d => d.PhysicalName)
+ .ToList()
+ .ForEach(db =>
+ {
+ FindMissing(work, db);
+ });
+ var theWork = TheGrade
+ .Distinct().ToList();
+ //theWork.Dump(nameof(theWork));
+ theWork.RemoveAll(tg => tg.AttributeGUID == Guid.Empty || tg.AttributeId == tg.AttributeGUID.ToString());
+ JsonConvert.SerializeObject(theWork, Newtonsoft.Json.Formatting.Indented).Dump("json");
+}
+
+public void FindMissing(List work, Database database)
+{
+ var db = new TypedDataContext(database.ConnectionString);
+ try
+ {
+ var dimensions = work.Select(w => w.DimensionGuid).Distinct();
+ var Score =
+ (from d in db.ScoreDimensions
+ join dg in db.ScoreDimensionGroups on d.DimensionGUID equals dg.DimensionGUID
+ join a in db.ScoreAttributes on dg.DimensionGroupGUID equals a.DimensionGroupGUID
+ where dimensions.Contains(d.DimensionGUID)
+ select new ScoreInfo(database.DatabaseName, database.DatabaseGuid, d.FriendlyName, d.DefaultHierarchyGUID, d.DimensionGUID, a.FriendlyName, a.AttributeGUID))
+ .ToList();
+ work.ToList()
+ .ForEach(w =>
+ {
+ var scores = Score.Where(sw => sw.DimensionGUID == w.DimensionGuid).ToList();
+ if (!scores.Any())
+ return;
+ var s = scores.FirstOrDefault(sw => sw.AttributeGUID == w.AttributeGuid);
+ if (s != null)
+ {
+ w.score = s;
+ return;
+ }
+ s = scores.FirstOrDefault(sw => sw.AttributeName == w.Name);
+ if (s == null)
+ {
+ w.score = scores.FirstOrDefault();
+ }
+ w.ByName = true;
+ w.score = s;
+ });
+ var missing = work.Where(w => w.score == null || w.ByName).ToList();
+ missing.ForEach(m =>
+ {
+ if (m.score == null)
+ m.score = new ScoreInfo(database.DatabaseName, database.DatabaseGuid, "", Guid.Empty, Guid.Empty, "", Guid.Empty);
+ m.score.DefinitionGuids = new List();
+ m.score.DefinitionGuids.AddRange(m.DefinitionGuids ?? new List());
+ });
+ var grades = missing.SelectMany(m => m.score.DefinitionGuids
+ .Select(dg => new DefinitionTranslationDto(dg, m.score.DatabaseName, m.score.DatabaseGuid, m.AttributeId, m.score.AttributeName, m.score.AttributeGUID)));
+
+ TheGrade.AddRange(grades);
+ //missing.Dump(database.DatabaseName);
+ }
+ catch (Exception e)
+ {
+
+ }
+
+}
+
+[JsonObject(MemberSerialization.OptIn)]
+public class DefinitionTranslationDto
+{
+ [JsonProperty]
+ public Guid DefinitionId { get; set; }
+ public string DatabaseName { get; set; }
+ [JsonProperty]
+ public Guid DatabaseGuid { get; set; }
+ public string AttributeId { get; set; }
+ public string AttributeName {get;set;}
+ [JsonProperty]
+ public Guid AttributeGUID { get; set; }
+
+ public DefinitionTranslationDto(Guid definitionId, string databaseName, Guid databaseGuid, string attributeId, string attributeName, Guid attributeGuid)
+ {
+ DefinitionId = definitionId;
+ DatabaseName = databaseName;
+ DatabaseGuid = databaseGuid;
+ AttributeId = attributeId;
+ AttributeName = attributeName;
+ AttributeGUID = attributeGuid;
+ }
+}
+
+public class ScoreInfo
+{
+ public string DatabaseName { get; set; }
+ public Guid DatabaseGuid { get; set; }
+ public string DimensionName { get; set; }
+ public Guid HierarchyGUID { get; set; }
+ public Guid DimensionGUID { get; set; }
+ public string AttributeName { get; set; }
+ public Guid AttributeGUID { get; set; }
+ public List DefinitionGuids { get; set; } = new List();
+
+ public ScoreInfo(string databaseName, Guid databaseGuid, string dimensionName, Guid hierarchyGUID, Guid dimensionGUID, string attributeName, Guid attributeGUID)
+ {
+ DatabaseName = databaseName;
+ DatabaseGuid = databaseGuid;
+ DimensionName = dimensionName;
+ HierarchyGUID = hierarchyGUID;
+ DimensionGUID = dimensionGUID;
+ AttributeName = attributeName;
+ AttributeGUID = attributeGUID;
+ }
+
+}
+
+public class WorkDto
+{
+ public Guid HierarchyGuid { get; set; }
+ public Guid DimensionGuid { get; set; }
+ public Guid AttributeGuid { get; set; }
+ public string HierarchyId { get; set; }
+ public string DimensionId { get; set; }
+ public string AttributeId { get; set; }
+ public string Name { get; set; }
+ public List DefinitionGuids { get; set; }
+ public bool ByName { get; set; } = false;
+ public ScoreInfo score { get; set; }
+}
+
+public void DumpScore()
+{
+ var Score =
+ (from d in ScoreDimensions
+ join dg in ScoreDimensionGroups on d.DimensionGUID equals dg.DimensionGUID
+ join a in ScoreAttributes on dg.DimensionGroupGUID equals a.DimensionGroupGUID
+ select new { DimensionName = d.FriendlyName, d.DefaultHierarchyGUID, d.DimensionGUID, AttributeName = a.FriendlyName, a.AttributeGUID });
+
+ Score
+ .GroupBy(sdm => new { sdm.DimensionName, sdm.DefaultHierarchyGUID, sdm.DimensionGUID }, (g, d) => new
+ {
+ Dimension = new
+ {
+ g.DimensionName,
+ g.DimensionGUID,
+ g.DefaultHierarchyGUID,
+ Attributes = d.Count()
+ },
+ Attributes = d.Select(sdm => new
+ {
+ sdm.AttributeName,
+ sdm.AttributeGUID
+ })
+ .OrderBy(sdm => sdm.AttributeName)
+ .ToList()
+ })
+ .OrderBy(ss => ss.Dimension.DimensionName)
+ .Dump();
+}
+
+// Define other methods and classes here
+
+#region *** Other classes ***
+
+IEnumerable GetList(RestClient client, string something)
+{
+ return Get>(client, something);
+}
+
+T Get(RestClient client, string something)
+{
+ client.BaseUrl = new Uri(BaseUrl + something);
+ RestRequest request = new RestRequest();
+ request.Method = Method.GET;
+ return JsonConvert.DeserializeObject(client.Execute(request).Content,
+ new JsonSerializerSettings
+ {
+ Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
+ {
+ args.ErrorContext.Error.Message.Dump();
+ args.ErrorContext.Handled = true;
+ }
+ });
+}
+
+public class DefinitionDto
+{
+ public Guid Id { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public Guid HierarchyGuid { get; set; }
+ public Guid DimensionGuid { get; set; }
+ public Guid AttributeGuid { get; set; }
+ public string HierarchyId { get; set; }
+ public string DimensionId { get; set; }
+ public string AttributeId { get; set; }
+ public DateTime DateCreated { get; set; }
+ public DateTime DateLastModified { get; set; }
+
+ public DefinitionDto()
+ {
+ }
+}
+
+public class Database
+{
+ public string Server { get; set; }
+ public Guid DatabaseGuid { get; set; }
+ public string DatabaseName { get; set; }
+ public string PhysicalName { get; set; }
+ public string OrgPin { get; set; }
+ public string AppVersion { get; set; }
+ public string Description { get; set; }
+ public Dictionary Fields { get; set; }
+ public string ConnectionString { get; set; }
+
+ public Database()
+ {
+
+ }
+
+ public Database(DataRow dr)
+ {
+ Server = dr.Field("ServerName");
+ DatabaseGuid = dr.Field("DatabaseGuid");
+ DatabaseName = dr.Field("DatabaseName");
+ PhysicalName = dr.Field("PhysicalName");
+ OrgPin = dr.Field("OrgPin");
+ AppVersion = dr.Field("AppVersion");
+ Description = dr.Field("Description");
+ Fields = new Dictionary();
+ foreach (DataColumn column in dr.Table.Columns)
+ {
+ var index = dr.Table.Columns.IndexOf(column);
+ Fields.Add(column.ColumnName, dr[index].ToString());
+ }
+ ConnectionString = BuildConnectionString(Server, PhysicalName);
+ }
+
+ object ToDump() => (object)new
+ {
+ //Server,
+ //DatabaseGuid,
+ DatabaseName,
+ //PhysicalName,
+ //OrgPin,
+ //AppVersion,
+ //Description,
+ ConnectionString
+ };
+}
+
+#endregion
+
+#region *** Other methods here ***
+
+public void DoTheDumping()
+{
+ if (dumpOptions)
+ {
+ OptionsDump();
+ }
+ if (dumpDBExclusions)
+ {
+ dbExclusions.Dump(nameof(dbExclusions));
+ serverExclusions.Dump(nameof(serverExclusions));
+ }
+ if (dumpDBTargets)
+ {
+ targetOrgPins.Dump(nameof(targetOrgPins));
+ targetDBs.Dump(nameof(targetDBs));
+ targetServers.Dump(nameof(targetServers));
+ }
+ if (dumpAppVersionTargets)
+ {
+ appVersions.Dump(nameof(appVersions));
+ }
+ if (dumpDBList)
+ {
+ databases.OrderBy(d => d.Server).ThenBy(d => d.PhysicalName).Dump($"{queryRegion} {nameof(databases)}");
+ }
+ if (dumpAppVersions)
+ {
+ databases
+ .GroupBy(db => db.AppVersion, (grp, data) => data.Select(x => x.AppVersion).First())
+ .OrderByDescending(db => db)
+ .Dump($"{queryRegion} {nameof(appVersions)}");
+ }
+}
+
+public static IOrderedEnumerable GetDatabases()
+{
+ switch (queryRegion)
+ {
+ case QueryRegions.Production:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc prod";
+ break;
+ case QueryRegions.Training:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc training";
+ break;
+ case QueryRegions.Oak:
+ smcServer = "ioak-sql-smc-01.sdt.local";
+ smcDB = "smc qa";
+ break;
+ default:
+ smcServer = "DDEN-SQL-SMC-01.sdt.local";
+ smcDB = "smc dev";
+ break;
+ }
+ if (dumpSmcSql) smcSql.Dump(nameof(smcSql));
+ List databases = new List();
+ var connStr = BuildConnectionString(smcServer, smcDB);
+ using (var conn = new SqlConnection(connStr))
+ {
+ var command = new SqlCommand(smcSql, conn);
+ command.CommandType = CommandType.Text;
+ var database = new DataSet();
+ conn.Open();
+ using (DbDataReader reader = command.ExecuteReader())
+ {
+ while (true)
+ {
+ var table = new DataTable();
+ database.Tables.Add(table);
+ table.Load(reader);
+ if (reader.IsClosed || !reader.NextResult()) break;
+ }
+ }
+ conn.Close();
+ databases = database.Tables[0].AsEnumerable().Select(dr => new Database(dr)).ToList();
+ databases = databases.Where(dr => !dbExclusions.Contains(dr.PhysicalName) && !serverExclusions.Contains(dr.Server)).ToList();
+ if (targetOrgPins.Any())
+ databases = databases.Where(dr => targetOrgPins.Contains(dr.OrgPin)).ToList();
+ if (targetServers.Any())
+ databases = databases.Where(dr => targetServers.Contains(dr.Server)).ToList();
+ if (targetDBs.Any())
+ databases = databases.Where(dr => targetDBs.Contains(dr.PhysicalName)).ToList();
+ if (appVersions.Any())
+ databases = databases.Where(dr => appVersions.Contains(dr.AppVersion)).ToList();
+ }
+ return databases
+ .OrderBy(d => d.Server).ThenBy(d => d.PhysicalName);
+}
+
+public static string BuildConnectionString(string server, string database, string username = null, string password = null)
+{
+ return username == null
+ ? $"data source={server};initial catalog='{database}';persist security info=True;Integrated Security=SSPI;"
+ : $"data source={server};initial catalog='{database}';User ID={username};pwd={password}";
+}
+
+#endregion
\ No newline at end of file
diff --git a/CrossDBQuery AppVersions.linq b/CrossDBQuery AppVersions.linq
new file mode 100644
index 0000000..05c6185
--- /dev/null
+++ b/CrossDBQuery AppVersions.linq
@@ -0,0 +1,382 @@
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.Dynamic
+ System.IO.Compression
+ System.Threading.Tasks
+
+
+#region *** Enumerations ***
+
+public enum QueryRegions
+{
+ Production,
+ Training,
+ Oak,
+ Dev
+}
+
+#endregion
+
+#region *** Options ***
+
+public static string crossDBQueryPath = @"D:\CrossDBQueries";
+public static QueryRegions queryRegion = QueryRegions.Production;
+public static bool dumpSmcSql = false;
+public static bool dumpDBList = true;
+public static bool dumpQueries = false;
+public static string[] appVersions = {
+
+};
+public static string[] serverExclusions = {
+ @"paonsql19.sdt.local\instance1",
+ @"paonsql17.sdt.local\instance1",
+ @"p0555-sql-01.sdt.local\instance1",
+ "P0000-sql-01.sdt.local",
+ "P9900-SQL-03.sdt.local",
+ "P9900-sql-05.sdt.local"
+};
+public static string[] targetServers = {
+};
+public static string[] targetDBs = {
+ //"jazz prd Gillette Childrens 20150417.1"
+ //"jazz prd Southern Illinois 20140408.1"
+ //"jazz tst Southern Illinois 20190918.1"
+ //"jazz dev master Prod"
+};
+#endregion *** Options ***
+
+#region *** SMC Settings and queries ***
+
+public static string smcSql => @"SELECT di.ServerName, di.DatabaseGUID, di.DatabaseName, di.PhysicalName, di.OrgPin, di.AppVersion, di.Description
+FROM [dbo].[viewDatabaseInfo] di
+WHERE 1=1"
++ (queryRegion == QueryRegions.Dev
+? @"
+ AND di.PhysicalName like 'jazz%'"
+: $@"
+ AND di.PhysicalName like 'jazz {(queryRegion != QueryRegions.Production ? "tst" : "prd")}%'
+ AND di.ServerName like 'p%'")
++ (serverExclusions.Any()
+? $@"
+ AND di.ServerName not in ('{string.Join("', '", serverExclusions)}')"
+: "")
++ (targetServers.Any()
+? $@"
+ AND di.ServerName in ('{string.Join("', '", targetServers)}')"
+: "")
++ (targetDBs.Any()
+? $@"
+ AND di.PhysicalName IN ('{string.Join(", '", targetDBs)}')
+"
+: "")
++ (appVersions.Any()
+? $@"
+ AND di.AppVersion in ('{string.Join("', '", appVersions)}')"
+: "");
+public static string smcServer { get; set; }
+public static string smcDB { get; set; }
+
+#endregion
+
+#region *** Program variables and settings ***
+
+public static int maxThreads = 8;
+public static int timeoutInMinutes = 2;
+public static IList crossDBQueryResults = new List();
+public static IOrderedEnumerable databases => GetDatabases();
+
+#endregion
+
+void Main()
+{
+ databases
+ .GroupBy(db => db.AppVersion, (grp, data) => data.Select(x => x.AppVersion).First())
+ .OrderByDescending(db => db)
+ .Dump("AppVersions");
+ /*
+ databases
+ .Select(db => new
+ {
+ db.AppVersion,
+ db.PhysicalName,
+ OrgPin = $"'{db.OrgPin}'" })
+ .Where(db => db.AppVersion != "2019.43")
+ .OrderByDescending(db => db.AppVersion)
+ .ThenBy(db => db.OrgPin)
+ .Dump("AppVersions");
+ */
+
+ // ExecuteCrossDBQueries()
+// //.Where(r => !r.Exceptions.Any() && (r.Results.First().Results.First().Count() != 2).Any())
+// .OrderBy(dbqr => dbqr.Results.Any() ? 0 : 1)
+// .ThenBy(dbqr => dbqr.Database.DatabaseName).Dump(nameof(crossDBQueryResults));
+}
+
+#region *** Other classes ***
+
+public class CrossDBQueryResult
+{
+ public Database Database { get; set; }
+ public List Results { get; set; }
+ public List Exceptions { get; set; }
+ public CrossDBQueryResult()
+ {
+ Results = new List();
+ Exceptions = new List();
+ }
+
+ public CrossDBQueryResult(Database database, string name, IEnumerable enumerable)
+ : this()
+ {
+ Database = database;
+ Results.Add(new SqlResults(name, enumerable));
+ }
+
+ public CrossDBQueryResult(Database database, Exception exception)
+ : this()
+ {
+ Database = database;
+ Exceptions.Add(exception.ExceptionMessage());
+ }
+
+ object ToDump() => Exceptions.Any() ? (object)new
+ {
+ Database,
+ Results,
+ Exceptions
+ } : new
+ {
+ Database,
+ Results
+ };
+}
+
+public class SqlResults
+{
+ public string Name { get; set; }
+ public IEnumerable Results { get; set; }
+ public SqlResults(string name, IEnumerable results)
+ {
+ Name = name;
+ Results = results;
+ }
+}
+
+public static class ExceptionExtension
+{
+ public static string ExceptionMessage(this Exception exception)
+ {
+ return $@"{exception.Message}{(exception.InnerException != null
+ ? $@"
+ {"".PadLeft(40, '-')}
+ {exception.InnerException.ExceptionMessage()}"
+ : "")}";
+ }
+}
+
+public class Database
+{
+ public string Server { get; set; }
+ public Guid DatabaseGuid { get; set; }
+ public string DatabaseName { get; set; }
+ public string PhysicalName { get; set; }
+ public string OrgPin { get; set; }
+ public string AppVersion { get; set; }
+ public string Description { get; set; }
+
+ public Database()
+ {
+
+ }
+
+ public Database(DataRow dr)
+ {
+ Server = dr.Field("ServerName");
+ DatabaseGuid = dr.Field("DatabaseGuid");
+ DatabaseName = dr.Field("DatabaseName");
+ PhysicalName = dr.Field("PhysicalName");
+ OrgPin = dr.Field("OrgPin");
+ AppVersion = dr.Field("AppVersion");
+ Description = dr.Field("Description");
+ }
+}
+
+public class ThreadWithState
+{
+ private string connectionString => BuildConnectionString(_server, _databaseName);
+ private Database _database;
+ private string _server => _database?.Server ?? string.Empty;
+ private string _databaseName => _database?.PhysicalName ?? string.Empty;
+ private string sqlName;
+ private IEnumerable _sqlQueries;
+
+ public ThreadWithState(Database database, KeyValuePair> sqlqueries)
+ {
+ _database = database;
+ sqlName = sqlqueries.Key;
+ _sqlQueries = sqlqueries.Value;
+ }
+
+ public void ThreadProc()
+ {
+ var crossDB = crossDBQueryResults.FirstOrDefault(x => x.Database == _database);
+ IEnumerable ThreadResults;
+ foreach (var sqlQuery in _sqlQueries)
+ {
+ try
+ {
+ ThreadResults = SelectDynamic(connectionString, sqlQuery);
+ var result = ThreadResults.First();
+ if (crossDB != null)
+ {
+ crossDB.Results.Add(new SqlResults(sqlName, ThreadResults));
+ }
+ else
+ {
+ crossDB = new CrossDBQueryResult(_database, sqlName, ThreadResults);
+ crossDBQueryResults.Add(crossDB);
+ }
+ }
+ catch (Exception ex)
+ {
+ if (crossDB != null)
+ {
+ crossDB.Exceptions.Add(new Exception(sqlQuery, ex).ExceptionMessage());
+ }
+ else
+ {
+ crossDBQueryResults.Add(new CrossDBQueryResult(_database, new Exception(sqlQuery, ex)));
+ }
+ }
+ }
+ }
+}
+
+#endregion
+
+#region *** Other methods here ***
+
+public static IOrderedEnumerable GetDatabases()
+{
+ switch (queryRegion)
+ {
+ case QueryRegions.Production:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc prod";
+ break;
+ case QueryRegions.Training:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc training";
+ break;
+ case QueryRegions.Oak:
+ smcServer = "ioak-sql-smc-01.sdt.local";
+ smcDB = "smc qa";
+ break;
+ default:
+ smcServer = "DDEN-SQL-SMC-01.sdt.local";
+ smcDB = "smc dev";
+ break;
+ }
+ if (dumpSmcSql) smcSql.Dump(nameof(smcSql));
+ IEnumerable dbInfos = new List();
+ var connStr = BuildConnectionString(smcServer, smcDB);
+ using (var conn = new SqlConnection(connStr))
+ {
+ conn.Open();
+ var command = new SqlCommand(smcSql, conn);
+ command.CommandType = CommandType.Text;
+ var table = new DataTable();
+ using (SqlDataReader reader = command.ExecuteReader())
+ {
+ table.BeginLoadData();
+ table.Load(reader);
+ table.EndLoadData();
+ conn.Close();
+ }
+ dbInfos = table.AsEnumerable().Select(dr => new Database(dr));
+ }
+ return dbInfos
+ .OrderBy(d => d.Server).ThenBy(d => d.PhysicalName);
+}
+
+public Dictionary> GetUserQueries(string path = null)
+{
+ var grp = 0;
+ return Directory.GetFiles(path ?? Directory.GetCurrentDirectory(), "*.sql", SearchOption.TopDirectoryOnly)
+ .ToDictionary(d => Path.GetFileNameWithoutExtension(d), f => File.ReadAllLines(f)
+ .Select(r =>
+ {
+ if (r.Equals("go", StringComparison.CurrentCultureIgnoreCase))
+ {
+ r = "";
+ return new { grp = grp++, r };
+ }
+ else
+ {
+ return new { grp, r };
+ }
+ }).GroupBy(r => r.grp, (x, lines) => string.Join(" ", lines.Select(l => l.r).Where(l => !string.IsNullOrEmpty(l)))));
+}
+
+public static IEnumerable SelectDynamic(string connStr, string sql)
+{
+ using (var conn = new SqlConnection(connStr))
+ {
+ conn.Open();
+ var command = new SqlCommand(sql, conn);
+ command.CommandType = CommandType.Text;
+ command.CommandTimeout = (int)TimeSpan.FromMinutes(timeoutInMinutes).TotalSeconds;
+ using (var reader = command.ExecuteReader())
+ {
+ var names = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();
+ foreach (IDataRecord record in reader as IEnumerable)
+ {
+ var expando = new ExpandoObject() as IDictionary;
+ foreach (var name in names)
+ expando[name] = record[name];
+
+ yield return expando;
+ }
+ }
+ conn.Close();
+ }
+}
+
+public IList ExecuteCrossDBQueries()
+{
+ if (dumpDBList) databases.Dump(nameof(databases));
+ var queries = GetUserQueries(crossDBQueryPath);
+ if (dumpQueries) queries.Dump(nameof(queries));
+ RunCrossDBQuery(databases, queries);
+ return crossDBQueryResults;
+}
+
+public void RunCrossDBQuery(IEnumerable databases, Dictionary> sqlList)
+{
+ var stopWatch = DateTime.Now;
+ var query = databases.AsParallel()
+ .SelectMany(database => sqlList.Where(sql => sql.Value.Any()).AsParallel()
+ .Select(sql => new ThreadWithState(database, sql)));
+ foreach (var q in query)
+ {
+ q.ThreadProc();
+ }
+ DateTime.Now.Subtract(stopWatch).TotalSeconds.Dump(nameof(stopWatch));
+}
+
+public static string BuildConnectionString(string server, string database, string username = null, string password = null)
+{
+ return username == null
+ ? $"data source={server};initial catalog='{database}';persist security info=True;Integrated Security=SSPI;"
+ : $"data source={server};initial catalog='{database}';User ID={username};pwd={password}";
+}
+
+#endregion
\ No newline at end of file
diff --git a/CrossDBQuery with useParms.linq b/CrossDBQuery with useParms.linq
new file mode 100644
index 0000000..e65ac37
--- /dev/null
+++ b/CrossDBQuery with useParms.linq
@@ -0,0 +1,484 @@
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.Dynamic
+ System.IO.Compression
+ System.Threading.Tasks
+ System.Data.Common
+
+
+#region *** Enumerations ***
+
+public enum QueryRegions
+{
+ Production,
+ Training,
+ Oak,
+ Dev
+}
+
+#endregion
+
+#region *** Options ***
+
+public static QueryRegions queryRegion = QueryRegions.Production;
+public static string crossDBQueryPath = @"D:\CrossDBQueries"; // This is the path to find the queries
+public static bool dumpSmcSql = false; // This flag will dump the smc sql to the result
+public static bool dumpDBList = false; // This flag will dump the databases to the result
+public static bool dumpQueries = true; // This flag will dump the queries to the result
+public static bool dumpDBExclusions = false; // This flag will dump the db and server exclusions
+public static bool dumpDBTargets = false; // This flag will dump the db and server targets
+public static bool dumpAppVersions = false; // This flag will dump the app versions used in the queryRegion
+public static bool dumpAppVersionTargets = false; // This flag will dump the app versions targets
+public static bool excludeExceptions = true;
+public static bool queryCompress = false;
+public static bool flatten = true; // This will flatten all of the results into a single list
+public static bool showStopWatch = false;
+public static bool noQueries = false; // This will stop the CrossDBQuery without running the queries
+public static bool useParms = true;
+
+#endregion
+
+public static Parms parms = new Parms
+{
+ name = "FY2020"
+};
+
+#region *** Database Selection ***
+
+public static string[] appVersions = { // This is a list of appVersions to filter for in the database list
+ //"2019.42"
+};
+public static string[] serverExclusions = { // This is a list of servers to exclude from the database list
+ @"paonsql19.sdt.local\instance1",
+ @"paonsql17.sdt.local\instance1",
+ @"p0555-sql-01.sdt.local\instance1",
+ "P0000-sql-01.sdt.local",
+ "P9900-SQL-03.sdt.local",
+ "P9900-sql-05.sdt.local"
+};
+public static string[] dbExclusions = { // This is a list of database physical names to exclude from the database list
+// "jazz tst Team AP Training 01",
+// "jazz tst Team AP Training 02",
+// "jazz tst Team AP Training 11",
+// "jazz tst Team AP Training 12",
+// "jazz tst Team AP Training 13",
+// "jazz tst Team AP Training 14"
+};
+public static string[] targetOrgPins = { // This is a list of org pins to target in the database list
+};
+public static string[] targetServers = { // This is a list of servers to target in the database list
+// "P9900-SQL-11.sdt.local"
+};
+public static string[] targetDBs = { // This is a list of database physicial names to target in the database list
+// "jazz prd Gillette Childrens 20150417.1"
+// "jazz prd Southern Illinois 20140408.1"
+// "jazz tst Southern Illinois 20190918.1"
+// "jazz dev master Prod"
+};
+
+#endregion *** Options ***
+
+#region *** SMC Settings and queries ***
+
+public static string smcSql => @"SELECT di.ServerName, di.DatabaseGUID, di.DatabaseName, di.PhysicalName, di.OrgPin, di.AppVersion, di.Description
+FROM [dbo].[viewDatabaseInfo] di
+WHERE 1=1"
++ (queryRegion == QueryRegions.Dev
+? @"
+ AND di.PhysicalName like 'jazz%'"
+: $@"
+ AND di.PhysicalName like 'jazz {(queryRegion != QueryRegions.Production ? "tst" : "prd")}%'
+ AND di.ServerName like 'p%'");
+public static string smcServer { get; set; }
+public static string smcDB { get; set; }
+
+#endregion
+
+#region *** Program variables and settings ***
+
+public static int maxThreads = 8;
+public static int timeoutInMinutes = 2;
+public static IList crossDBQueryResults = new List();
+public static IOrderedEnumerable databases => GetDatabases();
+public static Dictionary> queries = System.IO.Directory.Exists(crossDBQueryPath)
+ ? GetUserQueries(crossDBQueryPath)
+ : new Dictionary>();
+
+#endregion
+
+void Main()
+{
+ if (dumpDBExclusions)
+ {
+ dbExclusions.Dump(nameof(dbExclusions));
+ serverExclusions.Dump(nameof(serverExclusions));
+ }
+ if (dumpDBTargets)
+ {
+ targetOrgPins.Dump(nameof(targetOrgPins));
+ targetDBs.Dump(nameof(targetDBs));
+ targetServers.Dump(nameof(targetServers));
+ }
+ if (dumpAppVersionTargets)
+ {
+ appVersions.Dump(nameof(appVersions));
+ }
+ if (dumpDBList)
+ {
+ databases.OrderBy(d => d.Server).ThenBy(d => d.PhysicalName).Dump($"{queryRegion} {nameof(databases)}");
+ }
+ if (dumpAppVersions)
+ {
+ databases
+ .GroupBy(db => db.AppVersion, (grp, data) => data.Select(x => x.AppVersion).First())
+ .OrderByDescending(db => db)
+ .Dump($"{queryRegion} {nameof(appVersions)}");
+ }
+ if (noQueries) return;
+ var results = ExecuteCrossDBQueries()
+ //.Where(r => !r.Exceptions.Any() && (r.Results.First().Results.First().Count() != 2).Any())
+ //.Where(r => !r.Exceptions.Any() && r.Results.First().Name.Contains("Variation"))
+ .OrderBy(dbqr => dbqr.Results.Any() ? 0 : 1)
+ .ThenBy(dbqr => dbqr.Database.DatabaseName);
+ if (flatten)
+ {
+ results
+ .SelectMany(dbqr => dbqr.Results.SelectMany(r => r.Results).ToList())
+ .Dump(nameof(crossDBQueryResults));
+ }
+ else
+ {
+ results.Dump(nameof(crossDBQueryResults));
+ }
+}
+
+public class Parms
+{
+ public string name { get; set; }
+}
+
+#region *** Other classes ***
+
+public class CrossDBQueryResultLite
+{
+ public Database Database { get; set; }
+ public List Results { get; set; }
+}
+public class CrossDBQueryResult : CrossDBQueryResultLite
+{
+ public List Exceptions { get; set; }
+ public CrossDBQueryResult()
+ {
+ Results = new List();
+ Exceptions = new List();
+ }
+
+ public CrossDBQueryResult(Database database, string name, IEnumerable enumerable)
+ : this()
+ {
+ Database = database;
+ Results.Add(new SqlResults(name, enumerable));
+ }
+
+ public CrossDBQueryResult(Database database, Exception exception)
+ : this()
+ {
+ Database = database;
+ Exceptions.Add(exception.ExceptionMessage());
+ }
+
+ object ToDump() => excludeExceptions
+ ? (object)new
+ {
+ Database,
+ Results
+ }
+: new
+{
+ Database,
+ Results,
+ Exceptions
+};
+}
+
+public class SqlResults
+{
+ public string Name { get; set; }
+ public IEnumerable Results { get; set; }
+ public SqlResults(string name, IEnumerable results)
+ {
+ Name = name;
+ Results = results;
+ }
+}
+
+public static class ExceptionExtension
+{
+ public static string ExceptionMessage(this Exception exception)
+ {
+ return $@"{exception.Message}{(exception.InnerException != null
+ ? $@"
+ {"".PadLeft(40, '-')}
+ {exception.InnerException.ExceptionMessage()}"
+ : "")}";
+ }
+}
+
+public class Database
+{
+ public string Server { get; set; }
+ public Guid DatabaseGuid { get; set; }
+ public string DatabaseName { get; set; }
+ public string PhysicalName { get; set; }
+ public string OrgPin { get; set; }
+ public string AppVersion { get; set; }
+ public string Description { get; set; }
+ public Dictionary Fields { get; set; }
+
+ public Database()
+ {
+
+ }
+
+ public Database(DataRow dr)
+ {
+ Server = dr.Field("ServerName");
+ DatabaseGuid = dr.Field("DatabaseGuid");
+ DatabaseName = dr.Field("DatabaseName");
+ PhysicalName = dr.Field("PhysicalName");
+ OrgPin = dr.Field("OrgPin");
+ AppVersion = dr.Field("AppVersion");
+ Description = dr.Field("Description");
+ Fields = new Dictionary();
+ foreach (DataColumn column in dr.Table.Columns)
+ {
+ var index = dr.Table.Columns.IndexOf(column);
+ Fields.Add(column.ColumnName, dr[index].ToString());
+ }
+ }
+
+ object ToDump() => (object)new
+ {
+ Server,
+ DatabaseGuid,
+ DatabaseName,
+ PhysicalName,
+ OrgPin,
+ AppVersion,
+ Description
+ };
+}
+
+public class ThreadWithState
+{
+ private string connectionString => BuildConnectionString(_server, _databaseName);
+ private Database _database;
+ private string _server => _database?.Server ?? string.Empty;
+ private string _databaseName => _database?.PhysicalName ?? string.Empty;
+ private string sqlName;
+ private IEnumerable _sqlQueries;
+
+ public ThreadWithState(Database database, KeyValuePair> sqlqueries)
+ {
+ _database = database;
+ sqlName = sqlqueries.Key;
+ _sqlQueries = sqlqueries.Value;
+ }
+
+ public void ThreadProc()
+ {
+ var crossDB = crossDBQueryResults.FirstOrDefault(x => x.Database == _database);
+ IEnumerable ThreadResults;
+ foreach (var sqlQuery in _sqlQueries)
+ {
+ try
+ {
+ ThreadResults = SelectDynamic(_database, connectionString, sqlQuery);
+ var result = ThreadResults.First();
+ if (crossDB != null)
+ {
+ crossDB.Results.Add(new SqlResults(sqlName, ThreadResults));
+ }
+ else
+ {
+ crossDB = new CrossDBQueryResult(_database, sqlName, ThreadResults);
+ crossDBQueryResults.Add(crossDB);
+ }
+ }
+ catch (Exception ex)
+ {
+ if (crossDB != null)
+ {
+ crossDB.Exceptions.Add(new Exception(sqlQuery, ex).ExceptionMessage());
+ }
+ else
+ {
+ crossDBQueryResults.Add(new CrossDBQueryResult(_database, new Exception(sqlQuery, ex)));
+ }
+ }
+ }
+ }
+}
+
+#endregion
+
+#region *** Other methods here ***
+
+public static IOrderedEnumerable GetDatabases()
+{
+ switch (queryRegion)
+ {
+ case QueryRegions.Production:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc prod";
+ break;
+ case QueryRegions.Training:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc training";
+ break;
+ case QueryRegions.Oak:
+ smcServer = "ioak-sql-smc-01.sdt.local";
+ smcDB = "smc qa";
+ break;
+ default:
+ smcServer = "DDEN-SQL-SMC-01.sdt.local";
+ smcDB = "smc dev";
+ break;
+ }
+ if (dumpSmcSql) smcSql.Dump(nameof(smcSql));
+ List databases = new List();
+ var connStr = BuildConnectionString(smcServer, smcDB);
+ using (var conn = new SqlConnection(connStr))
+ {
+ var command = new SqlCommand(smcSql, conn);
+ command.CommandType = CommandType.Text;
+ var database = new DataSet();
+ conn.Open();
+ using (DbDataReader reader = command.ExecuteReader())
+ {
+ while (true)
+ {
+ var table = new DataTable();
+ database.Tables.Add(table);
+ table.Load(reader);
+ if (reader.IsClosed || !reader.NextResult()) break;
+ }
+ }
+ conn.Close();
+ databases = database.Tables[0].AsEnumerable().Select(dr => new Database(dr)).ToList();
+ databases = databases.Where(dr => !dbExclusions.Contains(dr.PhysicalName) && !serverExclusions.Contains(dr.Server)).ToList();
+ if (targetOrgPins.Any())
+ databases = databases.Where(dr => targetOrgPins.Contains(dr.OrgPin)).ToList();
+ if (targetServers.Any())
+ databases = databases.Where(dr => targetServers.Contains(dr.Server)).ToList();
+ if (targetDBs.Any())
+ databases = databases.Where(dr => targetDBs.Contains(dr.PhysicalName)).ToList();
+ if (appVersions.Any())
+ databases = databases.Where(dr => appVersions.Contains(dr.AppVersion)).ToList();
+ }
+ return databases
+ .OrderBy(d => d.Server).ThenBy(d => d.PhysicalName);
+}
+
+public static Dictionary> GetUserQueries(string path = null)
+{
+ var grp = 0;
+ var queries = Directory.GetFiles(path ?? Directory.GetCurrentDirectory(), "*.sql", SearchOption.TopDirectoryOnly)
+ .ToDictionary(d => Path.GetFileNameWithoutExtension(d), f => File.ReadAllLines(f)
+ .Select(r =>
+ {
+ if (r.Equals("go", StringComparison.CurrentCultureIgnoreCase))
+ {
+ r = "";
+ return new { grp = grp++, r };
+ }
+ else
+ {
+ return new { grp, r };
+ }
+ }).GroupBy(r => r.grp, (x, lines) => string.Join(queryCompress ? " " : "\r\n", lines.Select(l => l.r).Where(l => !string.IsNullOrEmpty(l)))));
+
+ // foreach (var key in queries.Keys)
+ // {
+ // foreach (var query in queries[key])
+ // {
+ // if (useParms)
+ // {
+ // FormattableString formatter = $"";
+ // string.Format(formatter, parms).Dump();
+ // }
+ // }
+ // }
+
+ if (dumpQueries)
+ queries.Dump(nameof(queries));
+ return queries;
+}
+
+public static IEnumerable SelectDynamic(Database db, string connStr, string sql)
+{
+ using (var conn = new SqlConnection(connStr))
+ {
+ var command = new SqlCommand(sql, conn);
+ command.CommandType = CommandType.Text;
+ command.CommandTimeout = (int)TimeSpan.FromMinutes(timeoutInMinutes).TotalSeconds;
+ var database = new DataSet();
+ conn.Open();
+ using (DbDataReader reader = command.ExecuteReader())
+ {
+ while (true)
+ {
+ var names = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();
+ foreach (IDataRecord record in reader as IEnumerable)
+ {
+ var expando = new ExpandoObject() as IDictionary;
+ if (flatten)
+ db.Fields.ForEach((x, y) => expando[x.Key] = x.Value);
+ foreach (var name in names)
+ expando[name] = record[name];
+
+ yield return expando;
+ }
+ if (reader.IsClosed || !reader.NextResult()) break;
+ }
+ }
+ conn.Close();
+ }
+}
+
+public IList ExecuteCrossDBQueries()
+{
+ RunCrossDBQuery(databases, queries);
+ return crossDBQueryResults;
+}
+
+public void RunCrossDBQuery(IEnumerable databases, Dictionary> sqlList)
+{
+ var stopWatch = DateTime.Now;
+ var query = databases.AsParallel()
+ .SelectMany(database => sqlList.Where(sql => sql.Value.Any()).AsParallel()
+ .Select(sql => new ThreadWithState(database, sql)));
+ foreach (var q in query)
+ {
+ q.ThreadProc();
+ }
+ var timer = DateTime.Now.Subtract(stopWatch).TotalSeconds;
+ if (showStopWatch) timer.Dump(nameof(stopWatch));
+}
+
+public static string BuildConnectionString(string server, string database, string username = null, string password = null)
+{
+ return username == null
+ ? $"data source={server};initial catalog='{database}';persist security info=True;Integrated Security=SSPI;"
+ : $"data source={server};initial catalog='{database}';User ID={username};pwd={password}";
+}
+
+#endregion
\ No newline at end of file
diff --git a/CrossDBQuery.linq b/CrossDBQuery.linq
new file mode 100644
index 0000000..567d2fc
--- /dev/null
+++ b/CrossDBQuery.linq
@@ -0,0 +1,503 @@
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.Dynamic
+ System.IO.Compression
+ System.Threading.Tasks
+ System.Data.Common
+
+
+#region *** Enumerations ***
+
+public enum QueryRegions
+{
+ Production,
+ Training,
+ Oak,
+ Dev
+}
+
+#endregion
+
+#region *** Options ***
+
+public static QueryRegions queryRegion = QueryRegions.Dev;
+public static string crossDBQueryPath = @"C:\Users\tlamb\Documents\CrossDBQueries"; // This is the path to find the queries
+public static bool checkForCILicensing = true; // This flag will add a column if the client db is licensed for CI
+public static bool dumpOptions = false; // This flag will dumpt this set of options
+public static bool dumpSmcSql = false; // This flag will dump the smc sql to the result
+public static bool dumpDBList = false; // This flag will dump the databases to the result
+public static bool dumpQueries = false; // This flag will dump the queries to the result
+public static bool dumpDBExclusions = false; // This flag will dump the db and server exclusions
+public static bool dumpDBTargets = false; // This flag will dump the db and server targets
+public static bool dumpAppVersions = false; // This flag will dump the app versions used in the queryRegion
+public static bool dumpAppVersionTargets = false; // This flag will dump the app versions targets
+public static bool excludeExceptions = true;
+public static bool queryCompress = false;
+public static bool flatten = true; // This will flatten all of the results into a single list
+public static bool showStopWatch = false;
+public static bool noQueries = false; // This will stop the CrossDBQuery without running the queries
+
+#endregion
+
+public static Parms parms = new Parms
+{
+ name = "FY2020"
+};
+
+#region *** Database Selection ***
+
+public static string[] appVersions = { // This is a list of appVersions to filter for in the database list
+ //"2020.31"
+};
+public static string[] serverExclusions = { // This is a list of servers to exclude from the database list
+ @"paonsql19.sdt.local\instance1",
+ @"paonsql17.sdt.local\instance1",
+ @"p0555-sql-01.sdt.local\instance1",
+ "P0000-sql-01.sdt.local",
+ "P9900-SQL-03.sdt.local",
+ "P9900-sql-05.sdt.local"
+};
+public static string[] dbExclusions = { // This is a list of database physical names to exclude from the database list
+};
+public static string[] targetOrgPins = { // This is a list of org pins to target in the database list
+// "0430", "0434", "0555", "0777"
+};
+public static string[] targetServers = { // This is a list of servers to target in the database list
+// "P9900-SQL-11.sdt.local"
+// "D0018-SQL-01.sdt.local"
+};
+public static string[] targetDBs = { // This is a list of database physicial names to target in the database list
+// "jazz prd Gillette Childrens 20150417.1"
+// "jazz prd Southern Illinois 20140408.1"
+// "jazz tst Southern Illinois 20190918.1"
+// "jazz dev master Prod"
+};
+
+#endregion *** Options ***
+
+#region *** SMC Settings and queries ***
+
+public static string smcSql => $@"SELECT di.ServerName, di.DatabaseGUID, di.DatabaseName, di.PhysicalName, di.OrgPin, di.AppVersion, di.Description
+{(checkForCILicensing ? " ,(select COUNT(*) from [dbo].[viewLicenseLink] l where l.NAME = 'ContinuousImprovement' and l.DatabaseGUID = di.DatabaseGUID and l.IsLicensed = 1) CI_LICENSED" : "")}
+FROM [dbo].[viewDatabaseInfo] di
+WHERE 1=1"
++ (queryRegion == QueryRegions.Dev
+? @"
+ AND di.PhysicalName like 'jazz%'"
+: $@"
+ AND di.PhysicalName like 'jazz {(queryRegion != QueryRegions.Production ? "tst" : "prd")}%'
+ AND di.ServerName like 'p%'");
+public static string smcServer { get; set; }
+public static string smcDB { get; set; }
+
+#endregion
+
+#region *** Program variables and settings ***
+
+public static int maxThreads = 8;
+public static int timeoutInMinutes = 2;
+public static IList crossDBQueryResults = new List();
+public static IOrderedEnumerable databases => GetDatabases();
+public static Dictionary> queries = System.IO.Directory.Exists(crossDBQueryPath)
+ ? GetUserQueries(crossDBQueryPath)
+ : new Dictionary>();
+
+#endregion
+
+void Main()
+{
+ if (dumpOptions)
+ {
+ OptionsDump();
+ }
+ if (dumpDBExclusions)
+ {
+ dbExclusions.Dump(nameof(dbExclusions));
+ serverExclusions.Dump(nameof(serverExclusions));
+ }
+ if (dumpDBTargets)
+ {
+ targetOrgPins.Dump(nameof(targetOrgPins));
+ targetDBs.Dump(nameof(targetDBs));
+ targetServers.Dump(nameof(targetServers));
+ }
+ if (dumpAppVersionTargets)
+ {
+ appVersions.Dump(nameof(appVersions));
+ }
+ if (dumpDBList)
+ {
+ databases.OrderBy(d => d.Server).ThenBy(d => d.PhysicalName).Dump($"{queryRegion} {nameof(databases)}");
+ }
+ if (dumpAppVersions)
+ {
+ databases
+ .GroupBy(db => db.AppVersion, (grp, data) => data.Select(x => x.AppVersion).First())
+ .OrderByDescending(db => db)
+ .Dump($"{queryRegion} {nameof(appVersions)}");
+ }
+ if (noQueries) return;
+ var results = ExecuteCrossDBQueries()
+ .OrderBy(dbqr => dbqr.Results.Any() ? 0 : 1)
+ .ThenBy(dbqr => dbqr.Database.DatabaseName);
+ if (flatten)
+ {
+ results
+ .SelectMany(dbqr => dbqr.Results.SelectMany(r => r.Results).ToList())
+ .Where(dbqr => dbqr.CI_LICENSED == "1")
+ .GroupBy(dbqr => dbqr.DatabaseGUID, (g,d) => d.First())
+ .Distinct()
+ .Dump(nameof(crossDBQueryResults));
+ }
+ else
+ {
+ results.Dump(nameof(crossDBQueryResults));
+ }
+}
+
+public void OptionsDump()
+{
+ var options = new
+ {
+ queryRegion,
+ crossDBQueryPath,
+ dumpOptions,
+ dumpSmcSql,
+ dumpDBList,
+ dumpQueries,
+ dumpDBExclusions,
+ dumpDBTargets,
+ dumpAppVersions,
+ dumpAppVersionTargets,
+ excludeExceptions,
+ queryCompress,
+ flatten,
+ showStopWatch,
+ noQueries
+ };
+ options.Dump(nameof(options));
+}
+
+public class Parms
+{
+ public string name { get; set; }
+}
+
+#region *** Other classes ***
+
+public class CrossDBQueryResultLite
+{
+ public Database Database { get; set; }
+ public List Results { get; set; }
+}
+public class CrossDBQueryResult : CrossDBQueryResultLite
+{
+ public List Exceptions { get; set; }
+ public CrossDBQueryResult()
+ {
+ Results = new List();
+ Exceptions = new List();
+ }
+
+ public CrossDBQueryResult(Database database, string name, IEnumerable enumerable)
+ : this()
+ {
+ Database = database;
+ Results.Add(new SqlResults(name, enumerable));
+ }
+
+ public CrossDBQueryResult(Database database, Exception exception)
+ : this()
+ {
+ Database = database;
+ Exceptions.Add(exception.ExceptionMessage());
+ }
+
+ object ToDump() => excludeExceptions
+ ? (object)new
+ {
+ Database,
+ Results
+ }
+: new
+{
+ Database,
+ Results,
+ Exceptions
+};
+}
+
+public class SqlResults
+{
+ public string Name { get; set; }
+ public IEnumerable Results { get; set; }
+ public SqlResults(string name, IEnumerable results)
+ {
+ Name = name;
+ Results = results;
+ }
+}
+
+public static class ExceptionExtension
+{
+ public static string ExceptionMessage(this Exception exception)
+ {
+ return $@"{exception.Message}{(exception.InnerException != null
+ ? $@"
+ {"".PadLeft(40, '-')}
+ {exception.InnerException.ExceptionMessage()}"
+ : "")}";
+ }
+}
+
+public class Database
+{
+ public string Server { get; set; }
+ public Guid DatabaseGuid { get; set; }
+ public string DatabaseName { get; set; }
+ public string PhysicalName { get; set; }
+ public string OrgPin { get; set; }
+ public string AppVersion { get; set; }
+ public string Description { get; set; }
+ public Dictionary Fields { get; set; }
+
+ public Database()
+ {
+
+ }
+
+ public Database(DataRow dr)
+ {
+ Server = dr.Field("ServerName");
+ DatabaseGuid = dr.Field("DatabaseGuid");
+ DatabaseName = dr.Field("DatabaseName");
+ PhysicalName = dr.Field("PhysicalName");
+ OrgPin = dr.Field("OrgPin");
+ AppVersion = dr.Field("AppVersion");
+ Description = dr.Field("Description");
+ Fields = new Dictionary();
+ foreach (DataColumn column in dr.Table.Columns)
+ {
+ var index = dr.Table.Columns.IndexOf(column);
+ Fields.Add(column.ColumnName, dr[index].ToString());
+ }
+ }
+
+ object ToDump() => (object)new
+ {
+ Server,
+ DatabaseGuid,
+ DatabaseName,
+ PhysicalName,
+ OrgPin,
+ AppVersion,
+ Description
+ };
+}
+
+public class ThreadWithState
+{
+ private string connectionString => BuildConnectionString(_server, _databaseName);
+ private Database _database;
+ private string _server => _database?.Server ?? string.Empty;
+ private string _databaseName => _database?.PhysicalName ?? string.Empty;
+ private string sqlName;
+ private IEnumerable _sqlQueries;
+
+ public ThreadWithState(Database database, KeyValuePair> sqlqueries)
+ {
+ _database = database;
+ sqlName = sqlqueries.Key;
+ _sqlQueries = sqlqueries.Value;
+ }
+
+ public void ThreadProc()
+ {
+ var crossDB = crossDBQueryResults.FirstOrDefault(x => x.Database == _database);
+ IEnumerable ThreadResults;
+ foreach (var sqlQuery in _sqlQueries)
+ {
+ try
+ {
+ ThreadResults = SelectDynamic(_database, connectionString, sqlQuery);
+ var result = ThreadResults.First();
+ if (crossDB != null)
+ {
+ crossDB.Results.Add(new SqlResults(sqlName, ThreadResults));
+ }
+ else
+ {
+ crossDB = new CrossDBQueryResult(_database, sqlName, ThreadResults);
+ crossDBQueryResults.Add(crossDB);
+ }
+ }
+ catch (Exception ex)
+ {
+ if (crossDB != null)
+ {
+ crossDB.Exceptions.Add(new Exception(sqlQuery, ex).ExceptionMessage());
+ }
+ else
+ {
+ crossDBQueryResults.Add(new CrossDBQueryResult(_database, new Exception(sqlQuery, ex)));
+ }
+ }
+ }
+ }
+}
+
+#endregion
+
+#region *** Other methods here ***
+
+public static IOrderedEnumerable GetDatabases()
+{
+ switch (queryRegion)
+ {
+ case QueryRegions.Production:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc prod";
+ break;
+ case QueryRegions.Training:
+ smcServer = "ioak-sql-smc-01";
+ smcDB = "smc training";
+ break;
+ case QueryRegions.Oak:
+ smcServer = "ioak-sql-smc-01.sdt.local";
+ smcDB = "smc qa";
+ break;
+ default:
+ smcServer = "DDEN-SQL-SMC-01.sdt.local";
+ smcDB = "smc dev";
+ break;
+ }
+ if (dumpSmcSql) smcSql.Dump(nameof(smcSql));
+ List databases = new List();
+ var connStr = BuildConnectionString(smcServer, smcDB);
+ using (var conn = new SqlConnection(connStr))
+ {
+ var command = new SqlCommand(smcSql, conn);
+ command.CommandType = CommandType.Text;
+ var database = new DataSet();
+ conn.Open();
+ using (DbDataReader reader = command.ExecuteReader())
+ {
+ while (true)
+ {
+ var table = new DataTable();
+ database.Tables.Add(table);
+ table.Load(reader);
+ if (reader.IsClosed || !reader.NextResult()) break;
+ }
+ }
+ conn.Close();
+ databases = database.Tables[0].AsEnumerable().Select(dr => new Database(dr)).ToList();
+ databases = databases.Where(dr => !dbExclusions.Contains(dr.PhysicalName) && !serverExclusions.Contains(dr.Server)).ToList();
+ if (targetOrgPins.Any())
+ databases = databases.Where(dr => targetOrgPins.Contains(dr.OrgPin)).ToList();
+ if (targetServers.Any())
+ databases = databases.Where(dr => targetServers.Contains(dr.Server)).ToList();
+ if (targetDBs.Any())
+ databases = databases.Where(dr => targetDBs.Contains(dr.PhysicalName)).ToList();
+ if (appVersions.Any())
+ databases = databases.Where(dr => appVersions.Contains(dr.AppVersion)).ToList();
+ }
+ return databases
+ .OrderBy(d => d.Server).ThenBy(d => d.PhysicalName);
+}
+
+public static Dictionary> GetUserQueries(string path = null)
+{
+ var grp = 0;
+ var queries = Directory.GetFiles(path ?? Directory.GetCurrentDirectory(), "*.sql", SearchOption.TopDirectoryOnly)
+ .ToDictionary(d => Path.GetFileNameWithoutExtension(d), f => File.ReadAllLines(f)
+ .Select(r =>
+ {
+ if (r.Equals("go", StringComparison.CurrentCultureIgnoreCase))
+ {
+ r = "";
+ return new { grp = grp++, r };
+ }
+ else
+ {
+ return new { grp, r };
+ }
+ }).GroupBy(r => r.grp, (x, lines) => string.Join(queryCompress ? " " : "\r\n", lines.Select(l => l.r).Where(l => !string.IsNullOrEmpty(l)))));
+
+ if (dumpQueries)
+ queries.Dump(nameof(queries));
+ return queries;
+}
+
+public static IEnumerable SelectDynamic(Database db, string connStr, string sql)
+{
+ using (var conn = new SqlConnection(connStr))
+ {
+ var command = new SqlCommand(sql, conn);
+ command.CommandType = CommandType.Text;
+ command.CommandTimeout = (int)TimeSpan.FromMinutes(timeoutInMinutes).TotalSeconds;
+ var database = new DataSet();
+ conn.Open();
+ using (DbDataReader reader = command.ExecuteReader())
+ {
+ while (true)
+ {
+ var names = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();
+ foreach (IDataRecord record in reader as IEnumerable)
+ {
+ var expando = new ExpandoObject() as IDictionary;
+ if (flatten)
+ {
+ foreach (var field in db.Fields)
+ {
+ expando[field.Key] = field.Value;
+ }
+ }
+ foreach (var name in names)
+ expando[name] = record[name];
+
+ yield return expando;
+ }
+ if (reader.IsClosed || !reader.NextResult()) break;
+ }
+ }
+ conn.Close();
+ }
+}
+
+public IList ExecuteCrossDBQueries()
+{
+ RunCrossDBQuery(databases, queries);
+ return crossDBQueryResults;
+}
+
+public void RunCrossDBQuery(IEnumerable databases, Dictionary> sqlList)
+{
+ var stopWatch = DateTime.Now;
+ var query = databases.AsParallel()
+ .SelectMany(database => sqlList.Where(sql => sql.Value.Any()).AsParallel()
+ .Select(sql => new ThreadWithState(database, sql)));
+ foreach (var q in query)
+ {
+ q.ThreadProc();
+ }
+ var timer = DateTime.Now.Subtract(stopWatch).TotalSeconds;
+ if (showStopWatch) timer.Dump(nameof(stopWatch));
+}
+
+public static string BuildConnectionString(string server, string database, string username = null, string password = null)
+{
+ return username == null
+ ? $"data source={server};initial catalog='{database}';persist security info=True;Integrated Security=SSPI;"
+ : $"data source={server};initial catalog='{database}';User ID={username};pwd={password}";
+}
+
+#endregion
\ No newline at end of file
diff --git a/CultureInfo with examples.linq b/CultureInfo with examples.linq
new file mode 100644
index 0000000..b684de2
--- /dev/null
+++ b/CultureInfo with examples.linq
@@ -0,0 +1,205 @@
+
+ <ProgramFilesX64>\Microsoft SDKs\Azure\.NET SDK\v2.9\bin\plugins\Diagnostics\Newtonsoft.Json.dll
+ <RuntimeDirectory>\System.ComponentModel.Composition.dll
+ <RuntimeDirectory>\System.ComponentModel.dll
+ <RuntimeDirectory>\System.Net.dll
+ <RuntimeDirectory>\System.Net.Http.dll
+ Amazon.Lambda.S3Events
+ AWSSDK.Core
+ AWSSDK.S3
+ TimeZoneNames
+ Amazon
+ Amazon.Auth.AccessControlPolicy
+ Amazon.Auth.AccessControlPolicy.ActionIdentifiers
+ Amazon.Internal
+ Amazon.Lambda.S3Events
+ Amazon.MissingTypes
+ Amazon.Runtime
+ Amazon.Runtime.CredentialManagement
+ Amazon.Runtime.CredentialManagement.Internal
+ Amazon.Runtime.EventStreams
+ Amazon.Runtime.EventStreams.Internal
+ Amazon.Runtime.Internal
+ Amazon.Runtime.Internal.Auth
+ Amazon.Runtime.Internal.Settings
+ Amazon.Runtime.Internal.Transform
+ Amazon.Runtime.Internal.Util
+ Amazon.Runtime.SharedInterfaces
+ Amazon.Runtime.SharedInterfaces.Internal
+ Amazon.S3
+ Amazon.S3.Encryption
+ Amazon.S3.Encryption.Internal
+ Amazon.S3.Internal
+ Amazon.S3.IO
+ Amazon.S3.Model
+ Amazon.S3.Model.Internal.MarshallTransformations
+ Amazon.S3.Transfer
+ Amazon.S3.Util
+ Amazon.Util
+ Amazon.Util.Internal
+ Amazon.Util.Internal.PlatformServices
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.ComponentModel.Composition
+ System.ComponentModel.Composition.Hosting
+ System.ComponentModel.Composition.Primitives
+ System.ComponentModel.Composition.ReflectionModel
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.Globalization
+ System.IO.Compression
+ System.Net.Http
+ System.Net.Http.Headers
+ System.Numerics
+ ThirdParty.BouncyCastle.Asn1
+ ThirdParty.BouncyCastle.Asn1.Utilities
+ ThirdParty.BouncyCastle.Math
+ ThirdParty.BouncyCastle.OpenSsl
+ ThirdParty.BouncyCastle.Utilities.IO.Pem
+ ThirdParty.Ionic.Zlib
+ ThirdParty.Json.LitJson
+ ThirdParty.MD5
+ TimeZoneNames
+
+
+void Main()
+{
+ var currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
+ // Get server DateTime.
+ DateTime date = DateTime.Now;
+ var amount = 12345.67M;
+
+ // Get a list of all Cultures
+ List cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures)
+ //.Where(ci => ci.Name == "en-MW")
+ .ToList();
+
+ // Add the Cultures to an ArrayList so we can sort them Alphabetically by name.
+ List cultureList = new List();
+ foreach (CultureInfo culture in cultures)
+ {
+ System.Threading.Thread.CurrentThread.CurrentCulture = culture;
+ RegionInfo regionInfo = default(RegionInfo);
+ if (culture.LCID != 4096 && !culture.Equals(CultureInfo.InvariantCulture))
+ {
+ regionInfo = new RegionInfo(culture.LCID);
+ }
+ string pattern = null;
+ switch (culture.NumberFormat.CurrencyPositivePattern)
+ {
+ case 0:
+ pattern = "{0}{1:N" + culture.NumberFormat.CurrencyDecimalDigits + "}";
+ break;
+ case 1:
+ pattern = "{1:N" + culture.NumberFormat.CurrencyDecimalDigits + "}{0}";
+ break;
+ case 2:
+ pattern = "{0} {1:N" + culture.NumberFormat.CurrencyDecimalDigits + "}";
+ break;
+ case 3:
+ pattern = "{1:N" + culture.NumberFormat.CurrencyDecimalDigits + "} {0}";
+ break;
+ }
+ cultureList.Add(new CultureData
+ {
+ EnglishName = culture.EnglishName,
+ Name = culture.Name,
+ Details = new CultureDetails
+ {
+ ShortDate_Format = culture.DateTimeFormat.ShortDatePattern,
+ ShortDate_Example = date.ToShortDateString(),
+ LongDate_Format = culture.DateTimeFormat.LongDatePattern,
+ LongDate_Example = date.ToLongDateString(),
+ ShortTime_Format = culture.DateTimeFormat.ShortTimePattern,
+ ShortTime_Example = date.ToShortTimeString(),
+ LongTime_Format = culture.DateTimeFormat.LongTimePattern,
+ LongTime_Example = date.ToLongTimeString(),
+ Currency_EnglishName = regionInfo?.CurrencyEnglishName ?? string.Empty,
+ Currency_NativeName = regionInfo?.CurrencyNativeName ?? string.Empty,
+ Currency_Format = pattern,
+ Currency_Example = string.Format(culture, "{0:C}", amount),
+ Currency_ExampleNeg = string.Format(culture, "{0:C}", (amount * -1)),
+ Currency_ExampleAlt = string.Format(culture, "{0:c}", amount),
+ Currency_ExampleAltNeg = string.Format(culture, "{0:C}", (amount * -1)),
+ Percentage_Format = $"{{{culture.NumberFormat.PercentPositivePattern}{culture.NumberFormat.PercentDecimalSeparator}{culture.NumberFormat.PercentDecimalDigits}:P}}",
+ Percentage_Symbol = culture.NumberFormat.PercentSymbol,
+ Percentage_Example = string.Format(culture, "{0:P}", .333)
+ },
+ MonthNames = MonthNames(culture),
+// TimeZones = TimeZones(currentCulture)
+ });
+ }
+
+ // Sort Cultures
+ //cultureList.Sort(new StringComparer());
+ cultureList
+ //.Where(l => l.Details.Percentage_Symbol != "%")
+ .OrderBy(c => c.EnglishName)
+ //.Where(c => c.EnglishName.Contains("Bermuda"))
+ .Dump(nameof(cultureList));
+
+ currentCulture = CultureInfo.GetCultures(CultureTypes.SpecificCultures).FirstOrDefault(c => c.EnglishName == "English (United States)");
+ System.Threading.Thread.CurrentThread.CurrentCulture = currentCulture;
+
+}
+
+class CultureDetails
+{
+ public string ShortDate_Format { get; set; }
+ public string ShortDate_Example { get; set; }
+ public string LongDate_Format { get; set; }
+ public string LongDate_Example { get; set; }
+ public string ShortTime_Format { get; set; }
+ public string ShortTime_Example { get; set; }
+ public string LongTime_Format { get; set; }
+ public string LongTime_Example { get; set; }
+ public string Currency_EnglishName { get; set; }
+ public string Currency_NativeName { get; set; }
+ public string Currency_Format { get; set; }
+ public string Currency_Example { get; set; }
+ public string Currency_ExampleNeg { get; set; }
+ public string Currency_ExampleAlt { get; set; }
+ public string Currency_ExampleAltNeg { get; set; }
+ public string Percentage_Format { get; set; }
+ public string Percentage_Symbol { get; set; }
+ public string Percentage_Example { get; set; }
+}
+class CultureData
+{
+ public string EnglishName { get; set; }
+ public string Name { get; set; }
+ public IDictionary MonthNames { get; set; }
+ public CultureDetails Details { get; set; }
+ public IEnumerable TimeZones { get; set; }
+}
+
+public IDictionary MonthNames(CultureInfo culture)
+{
+ return Enumerable.Range(1, 12).ToList()
+ .Select(mm => new { Key = mm, Value = culture.DateTimeFormat.GetMonthName(mm) })
+ .ToDictionary(item => item.Key, item => item.Value);
+}
+
+public IEnumerable TimeZones(CultureInfo culture)
+{
+ return TimeZoneInfo.GetSystemTimeZones();
+}
+
+public void TimeZoneList(CultureInfo culture)
+{
+ TimeZoneInfo.GetSystemTimeZones()
+ .SelectMany(tzi => new[] {
+ TZNames.GetAbbreviationsForTimeZone(tzi.Id, culture.Name).Daylight != TZNames.GetAbbreviationsForTimeZone(tzi.Id, culture.Name).Standard
+ ? new { Key = tzi.Id.Replace("Standard", "Daylight"), Value = TZNames.GetAbbreviationsForTimeZone(tzi.Id, culture.Name).Daylight }
+ : new { Key = tzi.Id, Value = TZNames.GetAbbreviationsForTimeZone(tzi.Id, culture.Name).Daylight },
+ new { Key = tzi.Id, Value = TZNames.GetAbbreviationsForTimeZone(tzi.Id, culture.Name).Standard }})
+ .GroupBy(x => x.Key)
+ .Select(g => g.First())
+ .ToDictionary(item => item.Key, item => item.Value)
+ .OrderBy(item => item.Key)
+ .Dump();
+}
\ No newline at end of file
diff --git a/DB Query Exceptions.linq b/DB Query Exceptions.linq
new file mode 100644
index 0000000..68ee169
--- /dev/null
+++ b/DB Query Exceptions.linq
@@ -0,0 +1,605 @@
+
+
+ 580b3b8d-cc02-4a68-8fbd-d1ec374a25f2
+ true
+ D0001-sql-11.sdt.local
+ jazz dev master Prod
+ true
+
+ Newtonsoft.Json
+ Newtonsoft.Json.Converters
+ Newtonsoft.Json.Linq
+ Newtonsoft.Json.Schema
+ Newtonsoft.Json.Serialization
+ System
+ System.ComponentModel
+ System.Diagnostics
+ System.Diagnostics.Tracing
+ System.IO.Compression
+ System.Linq.Dynamic
+
+
+// This link provides a good explanation of the Dynamic Query used in the DataTableJoins
+// https://ecs.syr.edu/faculty/fawcett/handouts/CoreTechnologies/CSharp/samples/CSharpSamples/LinqSamples/DynamicQuery/Dynamic%20Expressions.html
+//
+#region Options
+
+public static int TopRows = 1000; //int.MaxValue;
+public static int TableDumpDepth = int.MaxValue; //2;
+public static bool ShowTableQuery = false;
+public static bool ShowTablesToRemove = false;
+public static bool ShowTableNames = false;
+public static bool ShowTableList = false;
+public static bool ShowMissingUpdate = true;
+public static bool ShowMissingLegacy = false;
+
+#endregion
+
+private Connections connections = new Connections
+{
+ //Legacy = new ServerInstance("E0001-SQL-11.sdt.local", "StrataSphere"),
+ //Update = new ServerInstance("D0011-SQL-01.sdt.local", "StrataSphere")
+ Legacy = new ServerInstance("D0011-SQL-01.sdt.local", "jazz tst Southern Illinois 20190918.1"),
+ Update = new ServerInstance("D0011-SQL-01.sdt.local", "jazz tst Southern Illinois 20200331.1")
+ //Legacy = new ServerInstance("D0001-SQL-11.sdt.local", "jazz tst master prod 20190708.1"),
+ //Update = new ServerInstance("D0001-SQL-11.sdt.local", "jazz tst master prod")
+};
+// Hints:
+// 1) if you pass a null for the table list it will include all tables in the schema
+// 2) if you pass a table name like "C%"' it will only include all tables that start with C
+private List SchemasAndTablesToReview = new List {
+ new TablesAndColumns("cci", new[] {"%QVILineItemOpportunity%"}),
+ //new TablesAndColumns("clientdss", new [] { "FactPatientEncounterSummary" }),
+ //new TablesAndColumns("dss", new [] {"%CaseType%"}, new[] {"CaseTypeDRGMapping","CaseTypeFamilyMapping","FactCaseTypeMapping"}),
+ //new TablesAndColumns("fw", new []{ "DimAgeCohort"})
+};
+
+void Main()
+{
+ var tables = GetTables().ToList();
+ // Using 'D|' at the beginning of a column name implies that the sort order is descending for that column
+ tables.ForEach(table =>
+ {
+ switch (table.SchemaName)
+ {
+ case "cci":
+ switch (table.TableName)
+ {
+ case "ChargeCodeConfig":
+ table.Init(
+ new[] { "ChargeCodeID", "CostDriver" },
+ keyColumns: new[] { "ChargeCodeID", "CostDriver" }
+ );
+ break;
+ case "ChargeCodeCostDetail":
+ table.Init(
+ new[] { "EntityID", "ChargeCodeID" },
+ keyColumns: new[] { "EntityID", "ChargeCodeID" }
+ );
+ break;
+ case "Configuration":
+ table.Init(new[] { "D|FiscalYearID" }, new[] { "InitiativeIsSimplifiedWorkflow" }, new[] { "FiscalYearId" });
+ break;
+ case "InitiativeWorkflowHistory":
+ table.Init(new[] { "FromStep", "ToStep" });
+ break;
+ case "VariationEncounterSavingInfo":
+ table.Init(new[] { "EncounterRecordNumber" });
+ break;
+ case "FactOpportunityMetric":
+ table.Init(new[] { "FiscalYearID", "FiscalMonthID" });
+ break;
+ case "FactOpportunitySavings":
+ table.Init(new[] { "FiscalyYearID", "FiscalMonthID" });
+ break;
+ case "Initiative":
+ table.Init(new[] { "Name" });
+ break;
+ case "SystemSetting":
+ table.Excludes(new[] { "IsEncrypted" });
+ break;
+ case "QVILineItemOpportunity":
+ table.KeyColumns(new[] {"BreakdownID", "QVILineItemID", "QualityVariationEventID"});
+ break;
+ case "VariationOpportunity":
+ table.Init(
+ new[] { "CaseTypeEntityId", "CostDriver" },
+ keyColumns: new[] { "CostDriver", "CastTypeEntityId" }
+ );
+ break;
+ };
+ break;
+ case "clientdss":
+ switch (table.TableName)
+ {
+ case "FactPatientEncounterSummary":
+ table.Init(
+ new[] { "EncounterRecordNumber" },
+ new[] { "MikeQAtest1ID", "CustomJesseValidatingAllOthers", "CustomNewCalculatedSystemFieldasdf" },
+ where: "OBJ.MSDRGCaseTypeFamilyID <> 0 OR OBJ.APRDRGCaseTypeFamilyID <> 0");
+ break;
+ };
+ break;
+ case "dss":
+ switch (table.TableName)
+ {
+ case "CaseTypeDRGMapping":
+ table.Init(new[] { "DRGID" }, keyColumns: new[] { "DRGID" });
+ break;
+ case "CaseTypeEntity":
+ table.Init(new[] { "EntityID", "CaseTypeEntityID" },
+ keyColumns: new[] { "EntityID", "CaseTypeEntityID" });
+ break;
+ case "CaseTypeFamily":
+ table.Init(new[] { "Name", "CaseTypeFamilyGlobalID", "CaseTypeFamilyID" },
+ keyColumns: new[] { "Name", "CaseTypeFamilyGlobalID" });
+ break;
+ case "CaseTypeFamilyMappingAPRDRG":
+ table.Init(new[] { "APRDRGCode", "CaseTypeFamilyVersionID", "CaseTypeFamilyID" },
+ keyColumns: new[] { "APRDRGCode", "CaseTypeFamilyVersionID", "CaseTypeFamilyID" });
+ break;
+ case "CaseTypeFamilyMappingCPT":
+ table.Init(new[] { "CPTCode", "CaseTypeFamilyVersionID", "CaseTypeFamilyID" },
+ keyColumns: new[] { "CPTCode", "CaseTypeFamilyVersionID", "CaseTypeFamilyID" });
+ break;
+ case "CaseTypeFamilyMappingICD10":
+ table.Init(new[] { "ICD10Code", "MSDRGCode", "CaseTypeFamilyVersionID", "CaseTypeFamilyID" },
+ keyColumns: new[] { "ICD10Code", "MSDRGCode", "CaseTypeFamilyVersionID", "CaseTypeFamilyID" });
+ break;
+ case "CaseTypeFamilyVersion":
+ table.Init(new[] { "CaseTypeFamilyVersionID" },
+ keyColumns: new[] { "CaseTypeFamilyVersionID" });
+ break;
+ case "DimCaseType":
+ table.Init(new[] { "CaseTypeFamilyID", "CaseTypeId", "Name" }, jsonColumns: new[] { "CaseTypeConfigJSON" });
+ break;
+ };
+ break;
+ };
+ });
+ if (ShowTableNames) tables.Select(t => t.SchemaTable).Dump(nameof(ShowTableNames));
+ if (ShowTableList) tables.Dump(nameof(ShowTableList));
+ DoTheComparisons(connections, tables);
+}
+
+// Define other methods and classes here
+
+#region Gather Table Information
+
+public string GetTableQuery()
+{
+ var tableSchemas = string.Join(", ", SchemasAndTablesToReview.Select(sattr => $"'{sattr.SchemaName}'"));
+ var tableList = string.Join("\r\n", SchemasAndTablesToReview.ConvertAll(sattr =>
+ {
+ if (sattr.TableNames?.Any(cn => cn == "*") ?? true)
+ {
+ return $"\r\nWHEN c.TABLE_SCHEMA = '{sattr.SchemaName}' THEN 1";
+ }
+ else
+ {
+ var result = "";
+ if (sattr.TableNames.Any(tn => tn.Contains("%")))
+ {
+ result += sattr.TableNames.Where(tn => tn.Contains("%"))
+ .Aggregate("", (x, y) => $"{x}\r\nWHEN c.TABLE_SCHEMA = '{sattr.SchemaName}' AND c.TABLE_NAME LIKE '{y}' THEN 1");
+ }
+ if (sattr.TableNames.Any(tn => !tn.Contains("%")))
+ {
+ result += $"\r\nWHEN c.TABLE_SCHEMA = '{sattr.SchemaName}' AND c.TABLE_NAME IN ({string.Join(", ", sattr.TableNames.Where(tn => !tn.Contains("%")).Select(tn => $"'{tn}'"))}) THEN 1";
+ }
+ return result;
+ }
+ }));
+ return $@"SELECT c.TABLE_SCHEMA, c.TABLE_NAME, c.COLUMN_NAME, c.DATA_TYPE
+, CAST(CASE WHEN ccu.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END AS BIT) IsPrimaryKey
+FROM INFORMATION_SCHEMA.COLUMNS AS c
+LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc ON tc.TABLE_SCHEMA = c.TABLE_SCHEMA AND tc.TABLE_NAME = c.TABLE_NAME
+LEFT OUTER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS ccu ON ccu.TABLE_SCHEMA = tc.TABLE_SCHEMA AND ccu.TABLE_NAME = tc.TABLE_NAME AND ccu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME AND ccu.COLUMN_NAME = c.COLUMN_NAME
+WHERE c.TABLE_SCHEMA in ({tableSchemas})
+AND (CASE {tableList}
+ELSE 0
+END = 1)
+AND c.DATA_TYPE NOT IN ('datetime','uniqueidentifier', 'timestamp')
+AND NOT (c.COLUMN_NAME = 'RowID' and CAST(CASE WHEN ccu.CONSTRAINT_NAME IS NULL THEN 0 ELSE 1 END AS BIT) = 1)
+AND tc.CONSTRAINT_TYPE = 'Primary Key'
+ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION";
+}
+
+public IList GetTables()
+{
+ var tableQuery = GetTableQuery();
+ if (ShowTableQuery) tableQuery.Dump(nameof(ShowTableQuery));
+ var tablesToRemove = SchemasAndTablesToReview.Where(sattr => sattr.ExcludeTables.Any()).SelectMany(sattr => sattr.ExcludeTables.Select(et => new { sattr.SchemaName, ExcludeTable = et }));
+ var tables = ExecuteQueryDynamic(tableQuery).ToList();
+ if (tablesToRemove.Any())
+ {
+ if (ShowTablesToRemove)
+ tablesToRemove.Dump(nameof(ShowTablesToRemove));
+ tables.RemoveAll(x => tablesToRemove.Any(sattr => sattr.SchemaName == x.TABLE_SCHEMA && sattr.ExcludeTable == x.TABLE_NAME));
+ }
+ return tables
+ .GroupBy(x => new { x.TABLE_SCHEMA, x.TABLE_NAME },
+ (g, d) => new Table(g.TABLE_SCHEMA, g.TABLE_NAME,
+ d.Select(y => new Column(y.COLUMN_NAME, y.DATA_TYPE, y.IsPrimaryKey)).ToList()))
+ .ToList();
+}
+
+public class Table
+{
+ public string SchemaName { get; set; }
+ public string TableName { get; set; }
+ public IList Columns { get; set; } = new List();
+ public IList OrderBy { get; set; } = new List();
+ public IList Exclude { get; set; } = new List();
+ public IList KeyColumn { get; set; } = new List();
+ public IList Json { get; set; } = new List();
+ public string Where { get; set; } = "";
+ internal string SchemaTable => $"{SchemaName}.{TableName}";
+ public string SqlSelect => $"select TOP({TopRows}) \r\n\t{SelectColumns}\r\nfrom {SchemaTable} OBJ{Where}{OrderByStatement}";
+ internal string SelectColumns => !Columns?.Any() ?? true ? "*" : string.Join(",\r\n\t", Columns.Where(c => !Exclude.ToList().Contains(c.ColumnName)).Select(c => c.ColumnName));
+ internal string OrderByStatement => !OrderBy?.Any() ?? true ? "" : "\r\nOrder By " + string.Join(", ", OrderBy.Select(ob => $"{ob.ColumnName}{(ob.IsDescending ? " DESC" : "")}"));
+
+ public Table(string schemaName, string tableName)
+ {
+ SchemaName = schemaName;
+ TableName = tableName;
+ Columns = new List();
+ OrderBy = new List();
+ }
+
+ public Table(string schemaName, string tableName, IEnumerable columns)
+ : this(schemaName, tableName)
+ {
+ Columns = columns.ToList();
+ }
+
+ public Table(string schemaName, string tableName, IEnumerable columns, IEnumerable orderBy)
+ : this(schemaName, tableName, columns)
+ {
+ OrderBy = orderBy.ToList();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// Using 'D|' at the beginning of a column name implies that the sort order is descending for that column
+ ///
+ public void Init(IEnumerable orderBys = null, IEnumerable excludes = null, IEnumerable keyColumns = null, IEnumerable jsonColumns = null, string where = "")
+ {
+ Init(orderBys?.Distinct().Select(o => new OrderBy(o.Split('|').Last(), o.StartsWith("D|", StringComparison.CurrentCultureIgnoreCase))) ?? null,
+ excludes?.Distinct(), keyColumns?.Distinct(), jsonColumns?.Distinct(), where);
+ }
+
+ ///
+ ///
+ ///
+ ///
+ /// Using 'D|' at the beginning of a column name implies that the sort order is descending for that column
+ ///
+ public void Init(IEnumerable orderBys = null, IEnumerable excludes = null, IEnumerable keyColumns = null, IEnumerable jsonColumns = null, string where = "")
+ {
+ if (orderBys != null)
+ OrderBys(orderBys.Where(x => Columns.Select(c => c.ColumnName).Contains(x.ColumnName)));
+ if (excludes != null)
+ Excludes(excludes.Where(x => Columns.Select(c => c.ColumnName).Contains(x)));
+ if (keyColumns != null)
+ KeyColumns(keyColumns.Where(x => Columns.Select(c => c.ColumnName).Contains(x)));
+ if (jsonColumns != null)
+ JsonColumns(jsonColumns.Where(x => Columns.Select(c => c.ColumnName).Contains(x)));
+ if (!string.IsNullOrEmpty(where))
+ where = $"\r\nwhere {where}";
+ }
+
+ ///
+ /// Using 'D|' at the beginning of a column name implies that the sort order is descending for that column
+ ///
+ public void OrderBys(IEnumerable orderBys)
+ {
+ OrderBy.Clear();
+ ((List)OrderBy).AddRange(orderBys.Where(o => Columns.Select(c => c.ColumnName).Contains(o.ColumnName, StringComparer.CurrentCultureIgnoreCase)));
+ }
+
+ public void Excludes(IEnumerable excludes)
+ {
+ Exclude.Clear();
+ ((List)Exclude).AddRange(excludes.Where(e => Columns.Select(c => c.ColumnName).Contains(e, StringComparer.CurrentCultureIgnoreCase)));
+ }
+
+ public void KeyColumns(IEnumerable keyColumns)
+ {
+ KeyColumn.Clear();
+ ((List)KeyColumn).AddRange(keyColumns.Where(kc => Columns.Select(c => c.ColumnName).Contains(kc, StringComparer.CurrentCultureIgnoreCase)));
+ KeyColumn.Reverse().ToList().ForEach(kc => {
+ var col = Columns.Single(c => c.ColumnName == kc);
+ Columns.Remove(col);
+ Columns.Insert(0, col);
+ });
+ }
+
+ public void JsonColumns(IEnumerable jsonColumns)
+ {
+ Json.Clear();
+ ((List)Json).AddRange(jsonColumns.Where(jc => Columns.Select(c => c.ColumnName).Contains(jc, StringComparer.CurrentCultureIgnoreCase)));
+ }
+}
+
+public class Column
+{
+ public string ColumnName { get; set; }
+ public string DataType { get; set; }
+ public bool IsPrimaryKey { get; set; }
+ public Column(string columnName, string dataType = "", bool isPrimaryKey = false)
+ {
+ ColumnName = columnName;
+ DataType = dataType;
+ IsPrimaryKey = isPrimaryKey;
+ }
+}
+
+public class OrderBy
+{
+ public string ColumnName { get; set; }
+ public bool IsDescending { get; set; } = false;
+
+ public OrderBy(string columnName, bool isDescending = false)
+ {
+ ColumnName = columnName;
+ IsDescending = isDescending;
+ }
+
+}
+
+public class TablesAndColumns
+{
+ public string SchemaName { get; set; }
+ public IEnumerable TableNames { get; set; }
+ public IEnumerable ExcludeTables { get; set; }
+ public TablesAndColumns(string schemaName, IEnumerable tables = null, IEnumerable excludeTables = null)
+ {
+ SchemaName = schemaName;
+ TableNames = tables ?? new string[] { "*" };
+ ExcludeTables = excludeTables ?? new string[] { };
+ }
+}
+
+public class OrderByInformation
+{
+ public string TableName { get; set; }
+ public IEnumerable OrderBy { get; set; }
+ public OrderByInformation(string tableName, IEnumerable columns)
+ {
+ TableName = tableName;
+ OrderBy = columns
+ .Select(c =>
+ new OrderBy(c.StartsWith("D|") ? c.Substring(2) : c,
+ c.StartsWith("D|")));
+ }
+}
+
+public class ColumnsToExclude
+{
+ public string TableName { get; set; }
+ public IEnumerable ColumnNames { get; set; }
+ public ColumnsToExclude(string tableName, IEnumerable columns)
+ {
+ TableName = tableName;
+ ColumnNames = columns;
+ }
+}
+
+public class JsonColumns
+{
+ public string TableName { get; set; }
+ public IEnumerable ColumnNames { get; set; }
+ public JsonColumns(string tableName, IEnumerable columns)
+ {
+ TableName = tableName;
+ ColumnNames = columns;
+ }
+}
+
+#endregion
+
+#region Do the comparisons
+
+public void DoTheComparisons(Connections connections, IEnumerable tables)
+{
+ foreach (var table in tables)
+ {
+ var sql = table.SqlSelect;
+ var dataLegacy = GetData(connections.Legacy, sql, table.TableName).AsEnumerable().ToList();
+ var dataUpdate = GetData(connections.Update, sql, table.TableName).AsEnumerable().ToList();
+
+ var compare = new List();
+ var jsonColumns = table.Json.ToList() ?? null;
+ var keyColumns = table.KeyColumn.ToList() ?? null;
+ var idx = 0;
+ dataLegacy
+ .ForEach(legacyRow =>
+ {
+ DataRow updateRow = default(DataRow);
+ if (table.KeyColumn.Any())
+ {
+ var keys = string.Join("|", table.KeyColumn.Select(kc => $"{legacyRow.Field