/// <summary> /// Construct a CodeDOM that will find a record based on an external identifier and a configuration. /// </summary> public StaticConstructor(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) { // Initialize the object. this.ExternalInterfaceSchema = ExternalInterfaceSchema; this.middleTierTable = middleTierTable; // These are shorthand notations for values that are use often to construct the tables: string tableVariable = string.Format("{0}Table", middleTierTable.ElementTable.Name[0].ToString().ToLower() + middleTierTable.ElementTable.Name.Remove(0, 1)); string primaryKeyName = ExternalInterfaceSchema.RemoveXPath(middleTierTable.PrimaryKey.Fields[0]); // Method Header: // /// <summary>Initializes the static elements of an Object.</summary> // public static int TypeConstructor(string configurationId, string parameterId, string externalId) // { this.Comments.Add(new CodeCommentStatement(@"<summary>Initializes the static elements of an Object.</summary>", true)); this.Attributes = MemberAttributes.Final | MemberAttributes.Static; // // The table must be locked before the indices can be read into an accelerator array. // ServerMarketData.AlgorithmTypeLock.AcquireReaderLock(Timeout.Infinite); this.Statements.Add(new CodeCommentStatement(@"The table must be locked before the indices can be read into an accelerator array.")); this.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}Lock", ExternalInterfaceSchema.DataSetName, middleTierTable.ElementTable.Name)), "AcquireReaderLock", new CodeExpression[] { new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("System.Threading.Timeout"), "Infinite") })); // Get an accessor to the table schema information. This makes accessing information about the table much faster as // it doesn't need to do the lock checking each time it references the table. // // Accessor for the Algorithm Table. // ServerMarketData.AlgorithmDataTable algorithmTable = ServerMarketData.Algorithm; this.Statements.Add(new CodeCommentStatement(string.Format("Accessor for the {0} Table.", middleTierTable.ElementTable.Name))); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(string.Format("{0}.{1}DataTable", ExternalInterfaceSchema.DataSetName, middleTierTable.ElementTable.Name)), tableVariable, new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(ExternalInterfaceSchema.DataSetName), middleTierTable.ElementTable.Name))); // Indirect lookup operation using the external identifier to find a a row. // // This does an indirect lookup operation using the views created for the ExternalId columns. Take the index of the user // // identifier column calcualted above and use it to find a record containing the external identifier. // int externalIdIndex = GetExternalKeyIndex(configurationId, parameterId); // DataView[] externalIdIndexArray = new DataView[] { // algorithmTable.UKAlgorithmExternalId0, // algorithmTable.UKAlgorithmExternalId1}; // DataRowView[] dataRowView = externalIdIndexArray[externalIdIndex].FindRows(new object[] { // externalId}); this.Statements.Add(new CodeCommentStatement("This does an indirect lookup operation using the views created for the ExternalId columns. Take the index of the user")); this.Statements.Add(new CodeCommentStatement("identifier column calcualted above and use it to find a record containing the external identifier.")); CodeExpression[] userViewArray = new CodeExpression[this.middleTierTable.UniqueIndices.Length]; for (int index = 0; index < this.middleTierTable.UniqueIndices.Length; index++) { userViewArray[index] = new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(tableVariable), this.middleTierTable.UniqueIndices[index].Name); } this.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(middleTierTable.ElementTable.Name), "externalKeyArray"), new CodeArrayCreateExpression("DataView", userViewArray))); // // The table must be released after the array is constructed. // ServerMarketData.AlgorithmTypeLock.AcquireReaderLock(Timeout.Infinite); this.Statements.Add(new CodeCommentStatement(@"The table must be released after the array is constructed.")); this.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}Lock", ExternalInterfaceSchema.DataSetName, middleTierTable.ElementTable.Name)), "ReleaseReaderLock")); }
public ExternalInterfaceClass(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) { // Initialize the object this.ExternalInterfaceSchema = ExternalInterfaceSchema; this.middleTierTable = middleTierTable; // Find out if the class has external identifiers or has a parent table that uses external identifiers. The external // interface methods are only meaningful for resolving these external identifiers. bool isExternalInterfaceNeeded = middleTierTable.IsExternalIdClass || this.middleTierTable.ElementTable.Name == "Configuration"; foreach (XmlSchemaKeyref keyrefParent in middleTierTable.KeyrefParents) { XmlSchemaIdentityConstraint keyParent = ExternalInterfaceSchema.FindKey(keyrefParent.Refer.Name); XmlSchemaElement elementParent = ExternalInterfaceSchema.FindTable(ExternalInterfaceSchema.RemoveXPath(keyParent.Selector)); if (this.ExternalInterfaceSchema.HasExternalIdColumn(elementParent)) { isExternalInterfaceNeeded = true; } } // Construct the header for an inherited and independent class. if (middleTierTable.ElementBaseTable == null) { ExternalInterfaceClassWithoutBase(); } else { ExternalInterfaceClassWithBase(); } // The base classes need to define a persistent data store and gain a reference to the static, in-memory // data model. Inheritied classes don't need to be bothered because the base class has already defined these // resources. if (this.middleTierTable.ElementBaseTable == null) { // This field is a string which accesses the persistent memory store parameters from the configuration file. this.Members.Add(new PersistentStore(this.ExternalInterfaceSchema)); // This field provides access to the in-memory data model. this.Members.Add(new AdoDatabase(this.ExternalInterfaceSchema)); } // Optional Methods for finding a record based on an external identifier. if (middleTierTable.IsExternalIdClass && this.middleTierTable.ElementBaseTable == null) { this.Members.Add(new ExternalKeyArray(ExternalInterfaceSchema)); this.Members.Add(new StaticConstructor(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new GetExternalKeyIndex(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new FindKey(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new FindRequiredKey(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new FindOptionalKey(ExternalInterfaceSchema, middleTierTable)); } // Lock and Load this.Members.Add(new LoadLock(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new Load(ExternalInterfaceSchema, middleTierTable)); // If a table consists only of primary key elements (such as a mapping table), an update operation is undefined. That is, // there are no columns to update. if (middleTierTable.NonPrimaryKeyColumns != 0) { this.Members.Add(new UpdateLock(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new Update(ExternalInterfaceSchema, middleTierTable)); } // Delete and Archive Methods this.Members.Add(new DeleteLock(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new Delete(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new ArchiveLock(ExternalInterfaceSchema, middleTierTable)); this.Members.Add(new Archive(ExternalInterfaceSchema, middleTierTable)); }