public ExternalInterfaceNamespace(ExternalInterfaceSchema externalInterfaceSchema, MiddleTierTable middleTierTable) { // Initialize the object. this.externalInterfaceSchema = externalInterfaceSchema; this.middleTierTable = middleTierTable; // Name space and import declarations // namespace MarkThree.MiddleTier { // using System; // using System.Data; // using System.Xml; // using System.Runtime.Serialization; this.Name = externalInterfaceSchema.TargetNamespace; foreach (string reference in externalInterfaceSchema.References) { this.Imports.Add(new CodeNamespaceImport(reference)); } this.Imports.Add(new CodeNamespaceImport("MarkThree")); this.Imports.Add(new CodeNamespaceImport("System")); this.Imports.Add(new CodeNamespaceImport("System.Collections")); this.Imports.Add(new CodeNamespaceImport("System.Data")); this.Imports.Add(new CodeNamespaceImport("System.Data.SqlClient")); this.Types.Add(new ExternalInterfaceClass(externalInterfaceSchema, middleTierTable)); }
/// <summary> /// Construct a CodeDOM that will find a record based on an external identifier and a configuration. /// </summary> public FindRequiredKey(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) : base(ExternalInterfaceSchema, middleTierTable) { // These are shorthand notations for values that are use often to construct the tables: string tableVariable = string.Format("{0}Table", this.MiddleTierTable.ElementTable.Name[0].ToString().ToLower() + this.MiddleTierTable.ElementTable.Name.Remove(0, 1)); string primaryKeyName = this.ExternalInterfaceSchema.RemoveXPath(this.MiddleTierTable.PrimaryKey.Fields[0]); // Find the primary column element. XmlSchemaElement primaryColumnElement = null; foreach (XmlSchemaElement xmlSchemaElement in this.MiddleTierTable.ElementColumns) { if (xmlSchemaElement.Name == this.ExternalInterfaceSchema.RemoveXPath(this.MiddleTierTable.PrimaryKey.Fields[0])) { primaryColumnElement = xmlSchemaElement; } } // Method Header: // /// <summary>Finds a a Algorithm record using a configuration and an external identifier.</summary> // /// <param name="configurationId">Specified which mappings (user id columns) to use when looking up external identifiers.</param> // /// <param name="externalId">The external identifier for the record.</param> // public static int FindRequiredKey(string configurationId, string externalId) // { Type returnType = ((XmlSchemaDatatype)primaryColumnElement.ElementType).ValueType; this.Comments.Add(new CodeCommentStatement(string.Format("<summary>Finds a a {0} record using a configuration and an external identifier.</summary>", this.MiddleTierTable.ElementTable.Name), true)); this.Comments.Add(new CodeCommentStatement("<param name=\"configurationId\">Specified which mappings (user id columns) to use when looking up external identifiers.</param>", true)); this.Comments.Add(new CodeCommentStatement("<param name=\"externalId\">The external identifier for the record.</param>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; this.ReturnType = new CodeTypeReference(returnType); this.Name = "FindRequiredKey"; this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "configurationId")); this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "parameterId")); this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "externalId")); // // Look up the internal identifier using the configuration to select the ExternalId column and the external identifier to identify the record // int internalId = Algorithm.FindKey(configurationId, externalId); // if ((internalId == -1)) // { // throw new Exception(string.Format("The Algorithm table does not have a record identified by \'{0}\'", externalId)); // } CodeExpression returnValue = returnType == typeof(int) ? new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(int)), "MinValue") : new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(string)), "Empty"); this.Statements.Add(new CodeCommentStatement("Look up the internal identifier using the configuration to select the ExternalId column and the external identifier to identify the record")); CodeExpression[] exceptionVariables = new CodeExpression[] { new CodePrimitiveExpression(string.Format("The {0} table does not have a record identified by '{1}'", this.MiddleTierTable.ElementTable.Name, "{0}")), new CodeArgumentReferenceExpression("externalId") }; this.Statements.Add(new CodeVariableDeclarationStatement(returnType, "internalId", new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(this.MiddleTierTable.ElementTable.Name), "FindKey", new CodeExpression[] { new CodeArgumentReferenceExpression("configurationId"), new CodeArgumentReferenceExpression("parameterId"), new CodeArgumentReferenceExpression("externalId") }))); this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("internalId"), CodeBinaryOperatorType.IdentityEquality, returnValue), new CodeThrowExceptionStatement(new CodeObjectCreateExpression("Exception", new CodeExpression[] { new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(string)), "Format", exceptionVariables) })))); // // Return the internal identifier. // return internalId; this.Statements.Add(new CodeCommentStatement("Return the internal identifier.")); this.Statements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("internalId"))); }
/// <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 Update(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) : base(ExternalInterfaceSchema, middleTierTable) { // The method may have different formats depending on the use of identity columns or the presense of a base class. if (!this.MiddleTierTable.IsIdentityClass) { UpdateWithoutIdentity(); } else { if (this.MiddleTierTable.ElementBaseTable == null) { UpdateWithoutBase(); } else { UpdateWithBase(); } } }
/// <summary> /// Creates a procedure that collects table locks needed for the 'Delete' operation. /// </summary> /// <param name="externalInterfaceClass"></param> public DeleteLock(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) : base(ExternalInterfaceSchema, middleTierTable) { // These are shorthand notations for values that are use often to construct the tables: string tableVariable = string.Format("{0}Table", this.MiddleTierTable.ElementTable.Name[0].ToString().ToLower() + this.MiddleTierTable.ElementTable.Name.Remove(0, 1)); string rowVariable = string.Format("{0}Row", this.MiddleTierTable.ElementTable.Name[0].ToString().ToLower() + this.MiddleTierTable.ElementTable.Name.Remove(0, 1)); string tableTypeName = string.Format("{0}.{1}DataTable", this.ExternalInterfaceSchema.DataSetName, this.MiddleTierTable.ElementTable.Name); // /// <summary>Collects the table lock request(s) for an 'Delete' operation</summary> // /// <param name="requestLocks">A collection of table locks required for this operation.</param> // public static void Delete(Transaction transaction) // { this.Comments.Add(new CodeCommentStatement("<summary>Collects the table lock request(s) for an 'Delete' operation</summary>", true)); this.Comments.Add(new CodeCommentStatement(@"<param name=""adoTransaction"">A collection of table locks required for this operation</param>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; if (this.MiddleTierTable.ElementBaseTable != null) { this.Attributes |= MemberAttributes.New; } this.Name = "Delete"; this.Parameters.Add(new CodeParameterDeclarationExpression("AdoTransaction", "adoTransaction")); // // Call the internal methods to lock the tables required for an insert or update operation. // Shadows.Web.Service.Equity.Insert(transaction); // Shadows.Web.Service.Equity.Delete(transaction); this.Statements.Add(new CodeCommentStatement("Call the internal methods to lock the tables required for an insert or update operation.")); this.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ExternalInterfaceSchema.InternalNamespace, this.MiddleTierTable.ElementTable.Name)), "Delete", new CodeExpression[] { new CodeVariableReferenceExpression("adoTransaction") })); // // These table lock(s) are required for the 'Delete' operation. // transaction.Locks.AddReaderLock(ServerMarketData.ConfigurationLock); // transaction.Locks.AddWriterLock(ServerMarketData.AlgorithmLock); // transaction.Locks.AddReaderLock(ServerMarketData.AlgorithmTypeLock); this.Statements.Add(new CodeCommentStatement("These table lock(s) are required for the 'Delete' operation.")); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("adoTransaction"), "LockRequests"), "AddReaderLock", new CodeExpression[] { new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ExternalInterfaceSchema.DataSetName), string.Format("{0}Lock", this.MiddleTierTable.ElementTable.Name)) })); if (this.MiddleTierTable.IsExternalIdClass) { this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("adoTransaction"), "LockRequests"), "AddReaderLock", new CodeExpression[] { new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ExternalInterfaceSchema.DataSetName), "ConfigurationLock") })); } }
static int Main(string[] args) { try { // Defaults ExternalInterfaceCompiler.targetNamespace = string.Empty; ExternalInterfaceCompiler.internalNamespace = string.Empty; ExternalInterfaceCompiler.persistentStore = string.Empty; ExternalInterfaceCompiler.dataSetName = string.Empty; ExternalInterfaceCompiler.references = new ArrayList(); // The command line parser is driven by different states that are triggered by the flags read. Unless a flag has // been read, the command line parser assumes that it's reading the file name from the command line. argumentState = ArgumentState.InputFileName; // Parse the command line for arguments. foreach (string argument in args) { // Decode the current argument into a state change (or some other action). switch (argument) { case "-ds": argumentState = ArgumentState.DataSetName; continue; case "-i": argumentState = ArgumentState.InputFileName; continue; case "-is": argumentState = ArgumentState.InternalNamespace; continue; case "-ns": argumentState = ArgumentState.TargetNamespace; continue; case "-out": argumentState = ArgumentState.OutputFileName; continue; case "-ps": argumentState = ArgumentState.PersistentStore; continue; case "-ref": argumentState = ArgumentState.Reference; continue; case "-t": argumentState = ArgumentState.TargetTable; continue; } // The parsing state will determine which variable is read next. switch (argumentState) { case ArgumentState.DataSetName: ExternalInterfaceCompiler.dataSetName = argument; break; case ArgumentState.InputFileName: ExternalInterfaceCompiler.inputFileName = argument; break; case ArgumentState.InternalNamespace: ExternalInterfaceCompiler.internalNamespace = argument; break; case ArgumentState.OutputFileName: ExternalInterfaceCompiler.outputFileName = argument; break; case ArgumentState.PersistentStore: ExternalInterfaceCompiler.persistentStore = argument; break; case ArgumentState.Reference: ExternalInterfaceCompiler.references.Add(argument); break; case ArgumentState.TargetNamespace: ExternalInterfaceCompiler.targetNamespace = argument; break; case ArgumentState.TargetTable: ExternalInterfaceCompiler.targetTableName = argument; break; } // The default state is to look for the input file name on the command line. argumentState = ArgumentState.InputFileName; } // Throw a usage message back at the user if no file name was given. if (inputFileName == null || targetNamespace == string.Empty) { throw new Exception("Usage: Generator -i <input file name> -t <target table name>"); } // If the name of the internal namespace MarkThree.MiddleTier to find the commands that use only internal identifiers) was // not specified on the command line, then try to infer it from the target namespace. if (internalNamespace == string.Empty) { internalNamespace = targetNamespace.Replace(".External", string.Empty); } // If no output file name was specified, create one from the input file specification. if (outputFileName == null) { outputFileName = string.Format("{0}.cs", Path.GetFileNameWithoutExtension(inputFileName)); } StreamReader streamReader = new StreamReader(inputFileName); string inputContents = streamReader.ReadToEnd(); ExternalInterfaceSchema externalInterfaceSchema = new ExternalInterfaceSchema(inputContents); MiddleTierTable middleTierTable = new MiddleTierTable(externalInterfaceSchema, ExternalInterfaceCompiler.targetTableName); externalInterfaceSchema.InternalNamespace = ExternalInterfaceCompiler.internalNamespace; externalInterfaceSchema.TargetNamespace = ExternalInterfaceCompiler.targetNamespace; externalInterfaceSchema.PersistentStore = ExternalInterfaceCompiler.persistentStore; externalInterfaceSchema.DataSetName = ExternalInterfaceCompiler.dataSetName; externalInterfaceSchema.References = ExternalInterfaceCompiler.references; byte[] buffer = GenerateCode(externalInterfaceSchema, middleTierTable); FileStream outputStream = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.Write); outputStream.Write(buffer, 0, buffer.Length); outputStream.Close(); } catch (Exception exception) { Console.WriteLine(exception.Message); } return(0); }
/// <summary> /// Generate the code from the inputs. /// </summary> /// <param name="inputFileName">The name of the input file.</param> /// <param name="inputFileContent">The contents of the input file.</param> /// <returns>A buffer containing the generated code.</returns> protected static byte[] GenerateCode(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) { // Create a namespace MarkThree.MiddleTier add it to the module. This namespace MarkThree.MiddleTier all the relavent code in it. CodeCompileUnit codeCompileUnit = new CodeCompileUnit(); codeCompileUnit.Namespaces.Add(new ExternalInterfaceNamespace(ExternalInterfaceSchema, middleTierTable)); // This will generate the code from the abstract compile unit and dump it in a memory stream. MemoryStream memoryStream = new MemoryStream(); StreamWriter streamWriter = new StreamWriter(memoryStream, Encoding.UTF8); ExternalInterfaceCompiler.CodeProvider.GenerateCodeFromCompileUnit(codeCompileUnit, streamWriter, ExternalInterfaceCompiler.codeGeneratorOptions); streamWriter.Close(); // Return the source code converted to a stream of bytes. return(memoryStream.GetBuffer()); }
/// <summary> /// Creates a procedure that collects table locks needed for the 'Update' operation. /// </summary> /// <param name="externalInterfaceClass"></param> public UpdateLock(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) : base(ExternalInterfaceSchema, middleTierTable) { // These are shorthand notations for values that are use often to construct the tables: string tableVariable = string.Format("{0}Table", this.MiddleTierTable.ElementTable.Name[0].ToString().ToLower() + this.MiddleTierTable.ElementTable.Name.Remove(0, 1)); string rowVariable = string.Format("{0}Row", this.MiddleTierTable.ElementTable.Name[0].ToString().ToLower() + this.MiddleTierTable.ElementTable.Name.Remove(0, 1)); string tableTypeName = string.Format("{0}.{1}DataTable", this.ExternalInterfaceSchema.DataSetName, this.MiddleTierTable.ElementTable.Name); // /// <summary>Collects the table lock request(s) for an 'Update' operation</summary> // /// <param name="requestLocks">A collection of table locks required for this operation.</param> // public static void Update(Transaction transaction) // { this.Comments.Add(new CodeCommentStatement("<summary>Collects the table lock request(s) for an 'Update' operation</summary>", true)); this.Comments.Add(new CodeCommentStatement(@"<param name=""adoTransaction"">A collection of table locks required for this operation</param>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; if (this.MiddleTierTable.ElementBaseTable != null) { this.Attributes |= MemberAttributes.New; } this.Name = "Update"; this.Parameters.Add(new CodeParameterDeclarationExpression("AdoTransaction", "adoTransaction")); // // Call the internal methods to lock the tables required for an insert or update operation. // Shadows.Web.Service.Equity.Insert(transaction); // Shadows.Web.Service.Equity.Update(transaction); this.Statements.Add(new CodeCommentStatement("Call the internal methods to lock the tables required for an insert or update operation.")); this.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ExternalInterfaceSchema.InternalNamespace, this.MiddleTierTable.ElementTable.Name)), "Insert", new CodeExpression[] { new CodeVariableReferenceExpression("adoTransaction") })); this.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ExternalInterfaceSchema.InternalNamespace, this.MiddleTierTable.ElementTable.Name)), "Update", new CodeExpression[] { new CodeVariableReferenceExpression("adoTransaction") })); // // These table lock(s) are required for the 'Update' operation. // transaction.Locks.AddReaderLock(ServerMarketData.ConfigurationLock); // transaction.Locks.AddWriterLock(ServerMarketData.AlgorithmLock); // transaction.Locks.AddReaderLock(ServerMarketData.AlgorithmTypeLock); this.Statements.Add(new CodeCommentStatement("These table lock(s) are required for the 'Update' operation.")); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("adoTransaction"), "LockRequests"), "AddReaderLock", new CodeExpression[] { new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ExternalInterfaceSchema.DataSetName), string.Format("{0}Lock", this.MiddleTierTable.ElementTable.Name)) })); ArrayList arrayLock = new ArrayList(); foreach (XmlSchemaKeyref keyrefParent in this.MiddleTierTable.KeyrefParents) { // Get the name of the parent table. XmlSchemaIdentityConstraint keyParent = this.ExternalInterfaceSchema.FindKey(keyrefParent.Refer.Name); XmlSchemaElement elementParentTable = this.ExternalInterfaceSchema.FindTable(this.ExternalInterfaceSchema.RemoveXPath(keyParent.Selector)); // Collect the locks of all the parent tables. CollectTableLocks(arrayLock, elementParentTable); } // This will set a flag is the configuration table is needed to resolve external identifiers. bool needsCondigurationTable = this.MiddleTierTable.IsExternalIdClass; foreach (XmlSchemaElement elementParentTable in arrayLock) { if (this.ExternalInterfaceSchema.HasExternalIdColumn(elementParentTable)) { needsCondigurationTable = true; break; } } if (needsCondigurationTable) { this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("adoTransaction"), "LockRequests"), "AddReaderLock", new CodeExpression[] { new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ExternalInterfaceSchema.DataSetName), "ConfigurationLock") })); } foreach (XmlSchemaElement elementParentTable in arrayLock) { this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("adoTransaction"), "LockRequests"), "AddReaderLock", new CodeExpression[] { new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ExternalInterfaceSchema.DataSetName), string.Format("{0}Lock", elementParentTable.Name)) })); } }
/// <summary> /// Construct a CodeDOM that will find a record based on an external identifier and a configuration. /// </summary> public GetExternalKeyIndex(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) : base(ExternalInterfaceSchema, middleTierTable) { // These are shorthand notations for values that are use often to construct the tables: string tableVariable = string.Format("{0}Table", this.MiddleTierTable.ElementTable.Name[0].ToString().ToLower() + this.MiddleTierTable.ElementTable.Name.Remove(0, 1)); string primaryKeyName = this.ExternalInterfaceSchema.RemoveXPath(this.MiddleTierTable.PrimaryKey.Fields[0]); // Method Header: // /// <summary>Finds a a Algorithm record using a configuration and an external identifier.</summary> // /// <param name="configurationId">Specified which mappings (user id columns) to use when looking up external identifiers.</param> // /// <param name="externalId">The external (user supplied) identifier for the record.</param> // public static int GetExternalKeyIndex(string configurationId, string parameterId, string externalId) // { // Method Header: /// /// <summary>Calculates which index to uses when searching for external identifiers.</summary> /// /// <param name="configurationId">Specified which mappings (user id columns) to use when looking up external identifiers.</param> /// /// <param name="parameterId">The name of the parameter as specified in the configuration table.</param> /// /// <returns>An index into the array of keys to search for an external identifier.</returns> this.Comments.Add(new CodeCommentStatement(@"<summary>Calculates which index to uses when searching for external identifiers.</summary>", true)); this.Comments.Add(new CodeCommentStatement(@"<param name=""configurationId"">Specified which mappings (user id columns) to use when looking up external identifiers.</param>", true)); this.Comments.Add(new CodeCommentStatement(@"<param name=""parameterId"">The name of the parameter as specified in the configuration table.</param>", true)); this.Comments.Add(new CodeCommentStatement(@"<returns>An index into the array of keys to search for an external identifier.</returns>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; this.ReturnType = new CodeTypeReference(typeof(int)); this.Name = "GetExternalKeyIndex"; this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "configurationId")); this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "parameterId")); // Translate the configuration identifier into an index into the user Id columns: // // Translate the configurationId and the predefined parameter name into an index into the array of user ids. The index // // is where we expect to find the identifier. That is, an index of 1 will guide the lookup logic to use the external // // identifiers found in the 'ExternalId1' column. // ServerMarketData.ConfigurationRow configurationRow = ServerMarketData.Configuration.FindByConfigurationIdParameterId(configurationId, "AlgorithmId"); // int externalKeyIndex = 0; // if ((configurationRow != null)) // { // externalKeyIndex = configurationRow.Index; // } this.Statements.Add(new CodeCommentStatement("Translate the configurationId and the predefined parameter name into an index into the array of user ids. The index")); this.Statements.Add(new CodeCommentStatement("is where we expect to find the identifier. That is, an index of 1 will guide the lookup logic to use the external")); this.Statements.Add(new CodeCommentStatement("identifiers found in the 'ExternalId1' column.")); this.Statements.Add(new CodeVariableDeclarationStatement(typeof(int), "externalKeyIndex", new CodePrimitiveExpression(0))); CodeStatementCollection trueStatements = new CodeStatementCollection(); trueStatements.Add(new CodeCommentStatement("Attempt to find a external column specification for the given configuration and parameter. This record tells us")); trueStatements.Add(new CodeCommentStatement("which column to use in the array of external columns.")); trueStatements.Add(new CodeVariableDeclarationStatement(string.Format("{0}.ConfigurationRow", this.ExternalInterfaceSchema.DataSetName), "configurationRow", new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ExternalInterfaceSchema.DataSetName), "Configuration"), "FindByConfigurationIdParameterId", new CodeExpression[] { new CodeCastExpression(typeof(string), new CodeArgumentReferenceExpression("configurationId")), new CodeArgumentReferenceExpression("parameterId") }))); CodeExpression[] exceptionVariables = new CodeExpression[] { new CodePrimitiveExpression(@"The parameter {1} isn't defined for configuration '{0}'"), new CodeArgumentReferenceExpression("configurationId"), new CodeArgumentReferenceExpression("parameterId") }; CodeStatement externalKeyIndex = new CodeAssignStatement(new CodeVariableReferenceExpression("externalKeyIndex"), new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("configurationRow"), "ColumnIndex")); trueStatements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("configurationRow"), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), externalKeyIndex)); CodeStatement[] trueStatementBlock = new CodeStatement[trueStatements.Count]; trueStatements.CopyTo(trueStatementBlock, 0); this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression("configurationId"), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), trueStatementBlock)); // // This is the index into the array of keys to be used when searching for an external identifier. // return externalKeyIndex; this.Statements.Add(new CodeCommentStatement("This is the index into the array of keys to be used when searching for an external identifier.")); this.Statements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("externalKeyIndex"))); }
public ExternalInterfaceMethod(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) { // Initialize the object this.externalInterfaceSchema = ExternalInterfaceSchema; this.middleTierTable = middleTierTable; }
/// <summary> /// Construct a CodeDOM that will find a record based on an external identifier and a configuration. /// </summary> public FindKey(ExternalInterfaceSchema ExternalInterfaceSchema, MiddleTierTable middleTierTable) : base(ExternalInterfaceSchema, middleTierTable) { // These are shorthand notations for values that are use often to construct the tables: string tableVariable = string.Format("{0}Table", this.MiddleTierTable.ElementTable.Name[0].ToString().ToLower() + this.MiddleTierTable.ElementTable.Name.Remove(0, 1)); string primaryKeyName = this.ExternalInterfaceSchema.RemoveXPath(this.MiddleTierTable.PrimaryKey.Fields[0]); // Find the primary column element. XmlSchemaElement primaryColumnElement = null; foreach (XmlSchemaElement xmlSchemaElement in this.MiddleTierTable.ElementColumns) { if (xmlSchemaElement.Name == this.ExternalInterfaceSchema.RemoveXPath(this.MiddleTierTable.PrimaryKey.Fields[0])) { primaryColumnElement = xmlSchemaElement; } } // Method Header: // /// <summary>Finds a a Algorithm record using a configuration and an external identifier.</summary> // /// <param name="configurationId">Specified which mappings (user id columns) to use when looking up external identifiers.</param> // /// <param name="externalId">The external (user supplied) identifier for the record.</param> // public static int FindKey(string configurationId, string parameterId, string externalId) // { Type returnType = ((XmlSchemaDatatype)primaryColumnElement.ElementType).ValueType; this.Comments.Add(new CodeCommentStatement(string.Format("<summary>Finds a a {0} record using a configuration and an external identifier.</summary>", this.MiddleTierTable.ElementTable.Name), true)); this.Comments.Add(new CodeCommentStatement(@"<param name=""configurationId"">Specified which mappings (user id columns) to use when looking up external identifiers.</param>", true)); this.Comments.Add(new CodeCommentStatement(@"<param name=""parameterId"">The name of the parameter as specified in the configuration table.</param>", true)); this.Comments.Add(new CodeCommentStatement(@"<param name=""externalId"">The external (user supplied) identifier for the record.</param>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; this.ReturnType = new CodeTypeReference(returnType); this.Name = "FindKey"; this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "configurationId")); this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "parameterId")); this.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "externalId")); // This calculates the return value when there is no match. CodeExpression returnValue = returnType == typeof(int) ? new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(int)), "MinValue") : new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(string)), "Empty"); // // A missing key will never match a column. // if ((externalId == null)) // { // return; // } this.Statements.Add(new CodeCommentStatement("A missing key will never match a column.")); this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression("externalId"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)), new CodeStatement[] { new CodeMethodReturnStatement(returnValue) })); // 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.", this.MiddleTierTable.ElementTable.Name))); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(string.Format("{0}.{1}DataTable", this.ExternalInterfaceSchema.DataSetName, this.MiddleTierTable.ElementTable.Name)), tableVariable, new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ExternalInterfaceSchema.DataSetName), this.MiddleTierTable.ElementTable.Name))); // int externalKeyIndex = GetExternalKeyIndex(configurationId, parameterId); // DataView externalKeyView = externalKeyArray[externalKeyIndex]; // int recordIndex = externalKeyView.Find(new object[] {externalId}); // if (recordIndex == -1) // return -1; // return ((int)(externalIndexView[recordIndex].Row[objectTable.ObjectIdColumn])); this.Statements.Add(new CodeCommentStatement(@"Look for the record using the external identifier. The configuration selected the key to use, which effectively")); this.Statements.Add(new CodeCommentStatement(@"selected the external id column to use for the search. If a record is found in the view, a translation still needs")); this.Statements.Add(new CodeCommentStatement(@"to be made back to the original table before an index to the record can be returned to the caller.")); this.Statements.Add(new CodeVariableDeclarationStatement(typeof(int), "externalKeyIndex", new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(this.MiddleTierTable.ElementTable.Name), "GetExternalKeyIndex", new CodeExpression[] { new CodeArgumentReferenceExpression("configurationId"), new CodeArgumentReferenceExpression("parameterId") }))); this.Statements.Add(new CodeVariableDeclarationStatement(typeof(System.Data.DataView), "externalKeyView", new CodeArrayIndexerExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.MiddleTierTable.ElementTable.Name), "externalKeyArray"), new CodeExpression[] { new CodeVariableReferenceExpression("externalKeyIndex") }))); this.Statements.Add(new CodeVariableDeclarationStatement(typeof(int), "recordIndex", new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("externalKeyView"), "Find", new CodeExpression[] { new CodeArrayCreateExpression(typeof(object), new CodeExpression[] { new CodeArgumentReferenceExpression("externalId") }) }))); this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("recordIndex"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(-1)), new CodeMethodReturnStatement(returnValue))); this.Statements.Add(new CodeMethodReturnStatement(new CodeCastExpression(returnType, new CodeArrayIndexerExpression(new CodeFieldReferenceExpression(new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("externalKeyView"), new CodeExpression[] { new CodeVariableReferenceExpression("recordIndex") }), "Row"), new CodeExpression[] { new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(tableVariable), string.Format("{0}Column", primaryKeyName)) })))); }
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)); }