/// <summary> /// Creates a property that gets the collection of relationship between tables in the data model. /// </summary> /// <param name="dataModelSchema">The data model schema.</param> public RelationsProperty(DataModelSchema dataModelSchema) { // /// <summary> // /// Gets the collection of relations that link tables and allow navigation between parent tables and child tables. // /// </summary> // [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] // [global::System.ComponentModel.BrowsableAttribute(false)] // public static global::System.Data.DataRelationCollection Relations // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement("Gets the collection of relations that link tables and allow navigation between parent tables and child tables.", true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(DebuggerNonUserCodeAttribute)))); this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(BrowsableAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(false)))); this.Attributes = MemberAttributes.Public | MemberAttributes.Static; this.Type = new CodeGlobalTypeReference(typeof(DataRelationCollection)); this.Name = "Relations"; // get // { // global::Teraque.OrganizationPrincipal n222 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); // DataModelDataSet q223 = DataModel.tenantMap[n222.Tenant]; // return q223.Relations; CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeTargetDataModelStatement(dataModelSchema, targetDataSet, organizationPrincipal)); this.GetStatements.Add(new CodeMethodReturnStatement(new CodePropertyReferenceExpression(targetDataSet, "Relations"))); // } // } }
/// <summary> /// Creates a property to get a data table from the data model. /// </summary> /// <param name="tableSchema">A description of the table.</param> public TableProperty(TableSchema tableSchema) { // /// <summary> // /// Gets an accessor for the Account table. // /// </summary> // [global::System.ComponentModel.BrowsableAttribute(false)] // public static AccountDataTable Account // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Gets an accessor for the {0} table.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.AddRange(new CodeCustomAttributesForProperties()); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; this.Type = new CodeTypeReference(String.Format("{0}DataTable", tableSchema.Name)); this.Name = tableSchema.Name; // get // { // global::Teraque.OrganizationPrincipal n205 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); // TenantTarget t206 = DataModel.tenantMap[n205.Tenant]; // return t206.tableAccount; CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeTargetDataModelStatement(tableSchema.DataModel, targetDataSet, organizationPrincipal)); this.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(targetDataSet, String.Format("table{0}", tableSchema.Name)))); // } // } }
/// <summary> /// Generates a property that gets the lock for the data model. /// </summary> public DataLockProperty(DataModelSchema dataModelSchema) { // /// <summary> // /// Gets the lock for the data model. // /// </summary> // [global::System.ComponentModel.BrowsableAttribute(false)] // public static global::System.Threading.ReaderWriterLockSlim DataLock // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement("Gets the lock for the data model.", true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.AddRange(new CodeCustomAttributesForProperties()); this.Attributes = MemberAttributes.Public | MemberAttributes.Static; this.Type = new CodeGlobalTypeReference(typeof(ReaderWriterLockSlim)); this.Name = "DataLock"; // get // { // global::Teraque.OrganizationPrincipal d220 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); // DataModelDataSet p221 = DataModel.tenantMap[d220.Tenant]; // return p221.dataLock; // } CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeTargetDataModelStatement(dataModelSchema, targetDataSet, organizationPrincipal)); this.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(targetDataSet, "dataLock"))); // } }
/// <summary> /// Generates a property that gets the lock for the data model. /// </summary> public TenantTargetProperty(DataModelSchema dataModelSchema) { // /// <summary> // /// Gets the current transaction. // /// </summary> // [global::System.ComponentModel.BrowsableAttribute(false)] // public static TenantDataModel TenantDataModel // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement("Gets the tenant's data model.", true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.AddRange(new CodeCustomAttributesForProperties()); this.Attributes = MemberAttributes.Public | MemberAttributes.Static; this.Type = new CodeTypeReference(String.Format("Tenant{0}", dataModelSchema.Name)); this.Name = String.Format("Tenant{0}", dataModelSchema.Name); // get // { // global::Teraque.OrganizationPrincipal e8116 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); // return DataModel.tenantMap[e8116.Tenant]; CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add( new CodeMethodReturnStatement( new CodeIndexerExpression( new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(dataModelSchema.Name), "tenantMap"), new CodePropertyReferenceExpression(organizationPrincipal, "Organization")))); // } // } }
/// <summary> /// Creates a method to read an XML file. /// </summary> /// <param name="schema">The data model schema.</param> public ReadXmlMethod(DataModelSchema dataModelSchema) { // /// <summary> // /// Reads an XML file into the data model. // /// </summary> // /// <param name="fileName">The name of the file to read.</param> // public static void ReadXml(string fileName) // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement("Reads an XML file into the data model.", true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.Comments.Add(new CodeCommentStatement("<param name=\"fileName\">The name of the file to read.</param>", true)); this.Name = "ReadXml"; this.Attributes = MemberAttributes.Public | MemberAttributes.Static; this.Parameters.Add(new CodeParameterDeclarationExpression(new CodeGlobalTypeReference(typeof(String)), "fileName")); // global::Teraque.OrganizationPrincipal q8561 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); // DataModelDataSet i8562 = DataModel.tenantMap[q8561.Tenant]; // i8562.ReadXml(fileName); CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeTargetDataModelStatement(dataModelSchema, targetDataSet, organizationPrincipal)); this.Statements.Add( new CodeMethodInvokeExpression(targetDataSet, "ReadXml", new CodeArgumentReferenceExpression("fileName"))); // } }
/// <summary> /// Creates a method that loads records into the database from an external source. /// </summary> /// <param name="tableSchema">The schema used to describe the table.</param> public DestroyExMethod(TableSchema tableSchema) { // This shreds the list of parameters up into a metadata stucture that is helpful in extracting ordinary parameters // from those that need to be found in other tables using external identifiers. DestroyExParameterMatrix destroyParameterMatrix = new DestroyExParameterMatrix(tableSchema); // /// <summary> // /// Loads a record into the Department table from an external source. // /// </summary> // /// <param name="configurationId">Selects a configuration of unique indices used to resolve external identifiers.</param> // /// <param name="employeeKey">An optional unique key for the parent Employee record.</param> // /// <param name="managerKey">An optional unique key for the parent Manager record.</param> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [global::FluidTrade.Core.ClaimsPrincipalPermission(global::System.Security.Permissions.SecurityAction.Demand, ClaimType=global::FluidTrade.Core.ClaimTypes.Create, Resource=global::FluidTrade.Core.Resources.Application)] // public void DestroyEngineerEx(string configurationId, object[] employeeKey, object[] managerKey) { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Loads a record into the Department table from an external source.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(System.ServiceModel.OperationBehaviorAttribute)), new CodeAttributeArgument("TransactionScopeRequired", new CodePrimitiveExpression(true)))); //AR FB 408 - Remove Claims requirement //this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(ClaimsPrincipalPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Security.Permissions.SecurityAction)), "Demand")), // new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Create")), // new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { this.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">{1}</param>", parameterPair.Value.Name, parameterPair.Value.Description), true)); } this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Name = string.Format("Destroy{0}Ex", tableSchema.Name); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { this.Parameters.Add(parameterPair.Value.CodeParameterDeclarationExpression); } // // This provides a context for the middle tier transactions. // global::FluidTrade.Core.MiddleTierContext middleTierTransaction = global::FluidTrade.Core.MiddleTierContext.Current; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeCreateMiddleTierContextStatement(tableSchema.DataModel, transactionExpression)); // This will resolve the external identifiers and the build the primary key for the target record. The main idea is to // map elements from foreign rows into parameters that can be used to call the internal methods. foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { // Every internal update method requires a primary key. The external methods do not have this requirement and can // use any unique key. The translation between the external unique key and the internal primary key is created // here. if (parameterPair.Value is UniqueConstraintParameterItem) { this.Statements.AddRange(new CodeResolvePrimaryKeyStatements(tableSchema, transactionExpression, parameterPair.Value as UniqueConstraintParameterItem)); } } // At this point, all the external variables have been resolved and the primary index of the target row has been // calculated in the parameter matrix. This will perform the destroy with the internal method. this.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), string.Format("Destroy{0}", tableSchema.Name), destroyParameterMatrix.DestroyParameters)); }
/// <summary> /// Creates a property to return a collection of the tables in the data model. /// </summary> /// <param name="dataModelSchema">The data model schema.</param> public TablesProperty(DataModelSchema dataModelSchema) { // /// <summary> // /// Gets the collection of tables contained in the DataModel. // /// </summary> // [global::System.ComponentModel.BrowsableAttribute(false)] // public static global::System.Data.DataTableCollection Tables // { // get // { // global::Teraque.OrganizationPrincipal n222 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); // DataModelDataSet q223 = DataModel.tenantMap[n222.Tenant]; // return q223.Tables; // } // } this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Gets the collection of tables contained in the {0}.", dataModelSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.AddRange(new CodeCustomAttributesForProperties()); this.Attributes = MemberAttributes.Public | MemberAttributes.Static; this.Type = new CodeGlobalTypeReference(typeof(DataTableCollection)); this.Name = "Tables"; // get // { // global::Teraque.OrganizationPrincipal n222 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); // DataModelDataSet q223 = DataModel.tenantMap[n222.Tenant]; // return q223.Relations; CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add(new CodeTargetDataModelStatement(dataModelSchema, targetDataSet, organizationPrincipal)); this.GetStatements.Add(new CodeMethodReturnStatement(new CodePropertyReferenceExpression(targetDataSet, "Tables"))); // } // } }
/// <summary> /// Creates the CodeDOM for a method to delete a record from a table using transacted logic. /// </summary> /// <param name="tableSchema">A description of the table.</param> public DestroyMethod(TableSchema tableSchema) { // Create a matrix of parameters for this operation. DestroyParameterMatrix destroyParameterMatrix = new DestroyParameterMatrix(tableSchema); // This is the key used to identify the record to be deleted. CodeArgumentReferenceExpression primaryKeyExpression = null; foreach (KeyValuePair <string, ExternalParameterItem> externalParamterPair in destroyParameterMatrix.ExternalParameterItems) { if (externalParamterPair.Value is UniqueConstraintParameterItem) { primaryKeyExpression = new CodeArgumentReferenceExpression(externalParamterPair.Value.Name); } } // These are the names of common varibles generated by this CodeDOM. CodeTypeReference rowType = new CodeTypeReference(string.Format("{0}Row", tableSchema.Name)); CodeVariableReferenceExpression rowVariableExpression = new CodeRandomVariableReferenceExpression(); // /// <summary> // /// Deletes a Employee record. // /// </summary> // /// <param name="employeeId">The value for the EmployeeId column.</param> // /// <param name="rowVersion">The value for the RowVersion column.</param> // /// <param name="rowVersion">Used for Optimistic Concurrency Checking.</param> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [FluidTrade.Core.ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, ClaimType=FluidTrade.Core.ClaimTypes.Destroy, Resource=FluidTrade.Core.Resources.Application)] // public void DestroyEmployee(int employeeId, long rowVersion) { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Deletes a {0} record.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { this.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">{1}</param>", parameterPair.Value.Name, parameterPair.Value.Description), true)); } this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(System.ServiceModel.OperationBehaviorAttribute)), new CodeAttributeArgument("TransactionScopeRequired", new CodePrimitiveExpression(true)))); //AR FB 408 - Remove Claims requirement //this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(ClaimsPrincipalPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Security.Permissions.SecurityAction)), "Demand")), // new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Destroy")), // new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Name = string.Format("Destroy{0}", tableSchema.Name); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { this.Parameters.Add(parameterPair.Value.CodeParameterDeclarationExpression); } // This method can't do much without a primary key. if (tableSchema.PrimaryKey == null) { return; } // // This provides a context for the middle tier transactions. // global::FluidTrade.Core.MiddleTierContext middleTierTransaction = global::FluidTrade.Core.MiddleTierContext.Current; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeCreateMiddleTierContextStatement(tableSchema.DataModel, transactionExpression)); // // This record and any children in cascading relationships will be destroyed. // FluidTrade.UnitTest.Server.DataModel.EmployeeRow employeeRow = FluidTrade.UnitTest.Server.DataModel.Employee.FindByEmployeeId(new object[] { // employeeId}); // if ((employeeRow == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeId)); // } this.Statements.Add(new CodeVariableDeclarationStatement(rowType, rowVariableExpression.VariableName, new CodeFindByIndexExpression(tableSchema, primaryKeyExpression))); this.Statements.Add(new CodeCheckRecordExistsStatement(tableSchema, rowVariableExpression, primaryKeyExpression)); this.Statements.Add(new CodeAcquireRecordWriterLockExpression(transactionExpression, rowVariableExpression, tableSchema)); this.Statements.Add(new CodeAddLockToTransactionExpression(transactionExpression, rowVariableExpression)); // // This makes sure the record wasn't deleted between the time it was found and the time it was locked. // if ((employeeRow.RowState == System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeId)); // } this.Statements.Add(new CodeCheckRecordDetachedStatement(tableSchema, rowVariableExpression, primaryKeyExpression)); // // The Optimistic Concurrency check allows only one client to destroy a record at a time. // if ((employeeRow.RowVersion != rowVersion)) { // throw; // } this.Statements.Add(new CodeCheckConcurrencyStatement(tableSchema, rowVariableExpression, primaryKeyExpression)); // // Delete each of the child Engineer records in a cascade. // DataModel.EngineerRow[] employeeEngineerRowsByFK_Employee_Engineer = employeeRow.GetEngineerRows(); // for (int engineerIndex = 0; (engineerIndex < employeeEngineerRowsByFK_Employee_Engineer.Length); engineerIndex = (engineerIndex + 1)) { // // Get the next Engineer row in the list of children and lock it for the duration of the transaction. // DataModel.EngineerRow engineerRow = employeeEngineerRowsByFK_Employee_Engineer[engineerIndex]; // engineerRow.AcquireWriterLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(engineerRow); // // This makes sure the record wasn't deleted between the time it was found and the time it was locked. // if ((engineerRow.RowState != System.Data.DataRowState.Detached)) { // this.DestroyEngineer(engineerRow.EngineerId, engineerRow.RowVersion); // } // } // // Delete each of the child Manager records in a cascade. // DataModel.ManagerRow[] employeeManagerRowsByFK_Employee_Manager = employeeRow.GetManagerRows(); // for (int managerIndex = 0; (managerIndex < employeeManagerRowsByFK_Employee_Manager.Length); managerIndex = (managerIndex + 1)) { // // Get the next Manager row in the list of children and lock it for the duration of the transaction. // DataModel.ManagerRow managerRow = employeeManagerRowsByFK_Employee_Manager[managerIndex]; // managerRow.AcquireWriterLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(managerRow); // // This makes sure the record wasn't deleted between the time it was found and the time it was locked. // if ((managerRow.RowState != System.Data.DataRowState.Detached)) { // this.DestroyManager(managerRow.ManagerId, managerRow.RowVersion); // } // } // // Delete each of the child ProjectMember records in a cascade. // DataModel.ProjectMemberRow[] employeeProjectMemberRowsByFK_Employee_ProjectMember = employeeRow.GetProjectMemberRows(); // for (int projectMemberIndex = 0; (projectMemberIndex < employeeProjectMemberRowsByFK_Employee_ProjectMember.Length); projectMemberIndex = (projectMemberIndex + 1)) { // // Get the next ProjectMember row in the list of children and lock it for the duration of the transaction. // DataModel.ProjectMemberRow projectMemberRow = employeeProjectMemberRowsByFK_Employee_ProjectMember[projectMemberIndex]; // projectMemberRow.AcquireWriterLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(projectMemberRow); // // This makes sure the record wasn't deleted between the time it was found and the time it was locked. // if ((projectMemberRow.RowState != System.Data.DataRowState.Detached)) { // this.DestroyProjectMember(projectMemberRow.EmployeeId, projectMemberRow.ProjectId, projectMemberRow.RowVersion); // } // } foreach (KeyValuePair <string, RelationSchema> relationPair in tableSchema.ChildRelations) { if (relationPair.Value.ChildKeyConstraint.DeleteRule == ForeignKeyConstraintSchema.CascadeRules.Cascade) { // The child records in this table will be destroyed. TableSchema childTableSchema = relationPair.Value.ChildTable; // This collects the variables and types needed to build the statements to delete the child records. CodeVariableReferenceExpression iteratorVariableExpression = new CodeRandomVariableReferenceExpression(); CodeTypeReference rowArrayType = new CodeTypeReference(string.Format("{0}Row[]", childTableSchema.Name)); CodeVariableReferenceExpression rowArrayVariableExpression = new CodeRandomVariableReferenceExpression(); CodeTypeReference childRowType = new CodeTypeReference(string.Format("{0}Row", childTableSchema.Name)); CodeVariableReferenceExpression childRowVariableExpression = new CodeRandomVariableReferenceExpression(); CodeMethodReferenceExpression getMethodExpression = relationPair.Value.IsDistinctPathToChild ? new CodeMethodReferenceExpression(rowVariableExpression, string.Format("Get{0}Rows", childTableSchema.Name)) : new CodeMethodReferenceExpression(rowVariableExpression, string.Format("Get{0}RowsBy{1}", childTableSchema.Name, relationPair.Value.Name)); // // Delete each of the child Engineer records in a cascade. // DataModel.EngineerRow[] employeeEngineerRowsByFK_Employee_Engineer = employeeRow.GetEngineerRows(); // for (int engineerIndex = 0; (engineerIndex < employeeEngineerRowsByFK_Employee_Engineer.Length); engineerIndex = (engineerIndex + 1)) { this.Statements.Add(new CodeVariableDeclarationStatement(rowArrayType, rowArrayVariableExpression.VariableName, new CodeMethodInvokeExpression(getMethodExpression))); CodeIterationStatement forEachRecord = new CodeIterationStatement(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Int32)), iteratorVariableExpression.VariableName, new CodePrimitiveExpression(0)), new CodeBinaryOperatorExpression(iteratorVariableExpression, CodeBinaryOperatorType.LessThan, new CodePropertyReferenceExpression(rowArrayVariableExpression, "Length")), new CodeAssignStatement(iteratorVariableExpression, new CodeBinaryOperatorExpression(iteratorVariableExpression, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1)))); // // Get the next Engineer row in the list of children and lock it for the duration of the transaction. // DataModel.EngineerRow engineerRow = employeeEngineerRowsByFK_Employee_Engineer[engineerIndex]; // engineerRow.AcquireWriterLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(engineerRow); forEachRecord.Statements.Add(new CodeVariableDeclarationStatement(childRowType, childRowVariableExpression.VariableName, new CodeIndexerExpression(rowArrayVariableExpression, iteratorVariableExpression))); forEachRecord.Statements.Add(new CodeAcquireRecordWriterLockExpression(transactionExpression, childRowVariableExpression, tableSchema)); forEachRecord.Statements.Add(new CodeAddLockToTransactionExpression(transactionExpression, childRowVariableExpression)); // // This makes sure the record wasn't deleted between the time it was found and the time it was locked. // if ((engineerRow.RowState != System.Data.DataRowState.Detached)) { // this.DestroyEngineer(engineerRow.EngineerId, engineerRow.RowVersion); // } CodeConditionStatement ifDetatched = new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodePropertyReferenceExpression(childRowVariableExpression, "RowState"), CodeBinaryOperatorType.IdentityInequality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowState)), "Detached"))); DestroyParameterMatrix childMatrix = new DestroyParameterMatrix(childTableSchema); List <CodeExpression> childParameters = new List <CodeExpression>(); foreach (KeyValuePair <string, ExternalParameterItem> externalParameterPair in childMatrix.ExternalParameterItems) { if (externalParameterPair.Value is UniqueConstraintParameterItem) { List <CodeExpression> primaryKeyParameters = new List <CodeExpression>(); foreach (ColumnSchema primaryKeyColumn in childTableSchema.PrimaryKey.Columns) { primaryKeyParameters.Add(new CodePropertyReferenceExpression(childRowVariableExpression, primaryKeyColumn.Name)); } childParameters.Add(new CodeArrayCreateExpression(new CodeGlobalTypeReference(typeof(System.Object)), primaryKeyParameters.ToArray())); } else { childParameters.Add(new CodePropertyReferenceExpression(childRowVariableExpression, "RowVersion")); } } ifDetatched.TrueStatements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), string.Format("Destroy{0}", childTableSchema.Name), childParameters.ToArray())); forEachRecord.Statements.Add(ifDetatched); // } this.Statements.Add(forEachRecord); } } // System.Data.SqlClient.SqlCommand SqlCommand = new global::System.Data.SqlClient.SqlCommand("delete \"Employee\" where \"EmployeeId\"=@employeeId", middleTierTransaction.SqlConnection); // SqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@employeeId", System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, false, 0, 0, null, System.Data.DataRowVersion.Current, employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.EmployeeIdColumn])); // SqlCommand.ExecuteNonQuery(); if (tableSchema.IsPersistent) { CodeVariableReferenceExpression sqlCommandVariableExpression = new CodeRandomVariableReferenceExpression(); if (tableSchema.PrimaryKey != null) { string deleteCommandText = string.Format("delete \"{0}\"", tableSchema.Name); ColumnSchema[] keyColumns = tableSchema.PrimaryKey.Columns; if (keyColumns.Length > 0) { deleteCommandText += string.Format(" where \"{0}\"=@{1}", keyColumns[0].Name, CommonConversion.ToCamelCase(keyColumns[0].Name)); for (int keyIndex = 1; keyIndex < keyColumns.Length; keyIndex++) { deleteCommandText += string.Format(" and \"{0}\"=@{1}", keyColumns[1].Name, CommonConversion.ToCamelCase(keyColumns[1].Name)); } } this.Statements.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlCommand)), sqlCommandVariableExpression.VariableName, new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlCommand)), new CodePrimitiveExpression(deleteCommandText), new CodePropertyReferenceExpression(transactionExpression, "SqlConnection")))); foreach (ColumnSchema columnSchema in tableSchema.PrimaryKey.Columns) { string variableName = CommonConversion.ToCamelCase(columnSchema.Name); CodeExpression codeExpression = new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), string.Format("{0}Column", columnSchema.Name))); this.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(sqlCommandVariableExpression, "Parameters"), "Add", new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlParameter)), new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.ParameterDirection)), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowVersion)), "Current"), codeExpression))); } this.Statements.Add(new CodeMethodInvokeExpression(sqlCommandVariableExpression, "ExecuteNonQuery")); } } // // Delete the Employee record from the ADO data model. // middleTierTransaction.AdoResourceManager.AddRecord(employeeRow); // try { // FluidTrade.UnitTest.Server.DataModel.ReaderWriterLock.EnterWriteLock(); // FluidTrade.UnitTest.Server.DataModel.ProjectMember.AcquireLock(); // employeeRow.Delete(); // } // finally { // FluidTrade.UnitTest.Server.DataModel.ReaderWriterLock.ExitWriteLock(); // } this.Statements.Add(new CodeAddRecordToTransactionExpression(transactionExpression, rowVariableExpression)); CodeTryCatchFinallyStatement tryFinallyStatement = new CodeTryCatchFinallyStatement(); tryFinallyStatement.TryStatements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "EnterWriteLock")); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(rowVariableExpression, "Delete")); tryFinallyStatement.FinallyStatements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "ExitWriteLock")); this.Statements.Add(tryFinallyStatement); // DataModel.DestinationOrder.OnRowValidate(new DestinationOrderRowChangeEventArgs(pe9564f2717374e96a76d5222e2258784, System.Data.DataRowAction.Change)); this.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "OnRowValidate", new CodeObjectCreateExpression(string.Format("{0}RowChangeEventArgs", tableSchema.Name), rowVariableExpression, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowAction)), "Delete")))); // } }
/// <summary> /// Resolves the primary key. /// </summary> /// <param name="tableSchema">A description of a table.</param> /// <param name="uniqueConstraintParameterItem">A description of a unique key parameter.</param> public CodeResolvePrimaryKeyStatements(TableSchema tableSchema, CodeVariableReferenceExpression transactionExpression, UniqueConstraintParameterItem uniqueConstraintParameterItem, CodeExpression targetDataSet) { // This keeps us from having to pass this into the recursion. this.targetDataSet = targetDataSet; // All the external identifiers have been resolved. Now it is time to see if the record exists or if it has to be // created. Finding the record requires a unique index. If there are more than one unique index, a decision needs to // be made as to which one should be used. The configuration will drive that decision. If there is only one unique // constraint, then the decision doesn't need to be made. UniqueConstraintSchema[] uniqueConstraints = tableSchema.UniqueConstraintSchemas; CodeVariableReferenceExpression rowExpression = uniqueConstraintParameterItem.CodeVariableReferenceExpression; CodeVariableReferenceExpression uniqueKeyExpression = new CodeRandomVariableReferenceExpression(); // Optimized code is provided when there is only one unique constraint on a table. This saves the database // administrator from having to configure every single table in the data model with a description of the unique index // that is to be used when finding a row in that table. If there is more than one unique constraint on a table, a // value will need to be provided in the configuration to tell the loader which one to use. if (uniqueConstraints.Length == 1) { // If there are no foreign keys attached to the selected primary key, then the key value is taken directly from // the input parameters. ForeignKeyConstraintSchema foreignKeyConstraintSchema = uniqueConstraints[0].ForeignKey; if (foreignKeyConstraintSchema == null) { this.Add(new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(Object[])), uniqueKeyExpression.VariableName, new CodeArgumentReferenceExpression(uniqueConstraintParameterItem.Name))); this.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("{0}Row", tableSchema.Name)), uniqueConstraintParameterItem.CodeVariableReferenceExpression.VariableName, new CodeMethodInvokeExpression( new CodePropertyReferenceExpression( new CodeFieldReferenceExpression(targetDataSet, String.Format("table{0}", tableSchema.Name)), uniqueConstraints[0].Name), "Find", uniqueKeyExpression))); } else { // When there are foreign keys associated with the selected unique constraint, the foreign keys are resolved // using the key passed in as a parameter to this method. This is a recursive operation that digs through the // table hierarchy until a record is found that matches the key. CodeVariableReferenceExpression rootRowExpression = new CodeRandomVariableReferenceExpression(); this.AddRange( new CodeResolveForeignKeyExpression( rootRowExpression, transactionExpression, new CodeArgumentReferenceExpression(uniqueConstraintParameterItem.Name), foreignKeyConstraintSchema, targetDataSet)); List <CodeExpression> keyItems = new List <CodeExpression>(); for (int columnIndex = 0; columnIndex < tableSchema.PrimaryKey.Columns.Length; columnIndex++) { keyItems.Add(new CodePropertyReferenceExpression(rootRowExpression, foreignKeyConstraintSchema.RelatedColumns[columnIndex].Name)); } this.Add( new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(Object[])), uniqueKeyExpression.VariableName, new CodeArrayCreateExpression(new CodeGlobalTypeReference(typeof(Object)), keyItems.ToArray()))); this.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("{0}Row", tableSchema.Name)), uniqueConstraintParameterItem.CodeVariableReferenceExpression.VariableName, new CodeMethodInvokeExpression( new CodePropertyReferenceExpression( new CodeFieldReferenceExpression(targetDataSet, String.Format("table{0}", tableSchema.Name)), uniqueConstraints[0].Name), "Find", uniqueKeyExpression))); } } else { // // This will find and lock the configuration row that selects the unique constraint for this table. // object[] configurationKey3 = new object[] { // configurationId, // "ObjectTree"}; // ConfigurationRow configurationRow4 = DataModel.Configuration.ConfigurationKey.Find(configurationKey3); // if ((configurationRow4 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::Teraque.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey3)); // } // configurationRow4.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(configurationRow4); // if ((configurationRow4.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::Teraque.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey3)); // } CodeVariableReferenceExpression configurationKeyExpression = new CodeRandomVariableReferenceExpression(); this.Add( new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(Object[])), configurationKeyExpression.VariableName, new CodeKeyCreateExpression(new CodeArgumentReferenceExpression("configurationId"), new CodePrimitiveExpression(tableSchema.Name)))); CodeVariableReferenceExpression configurationRowExpression = new CodeRandomVariableReferenceExpression(); this.Add( new CodeVariableDeclarationStatement( new CodeTypeReference("ConfigurationRow"), configurationRowExpression.VariableName, new CodeMethodInvokeExpression( new CodePropertyReferenceExpression( new CodeFieldReferenceExpression(targetDataSet, "tableConfiguration"), "ConfigurationKey"), "Find", configurationKeyExpression))); TableSchema configurationTableSchema = tableSchema.DataModel.Tables["Configuration"]; this.Add(new CodeCheckRecordExistsStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); this.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, configurationRowExpression, tableSchema.DataModel)); this.Add(new CodeAddLockToTransactionExpression(transactionExpression, configurationRowExpression)); this.Add(new CodeCheckRecordDetachedStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); // // This constructs a key based on the unique constraint specified by the configuration. // object[] objectTreeKey2 = null; // if ((configurationRow4.IndexName == "ObjectTreeKeyExternalId0")) { // objectTreeKey2 = new object[] { // externalId0}; // } // if ((configurationRow4.IndexName == "ObjectTreeKeyParentIdChildId")) { // objectTreeKey2 = new object[] { // parentId, // childId}; // } CodePropertyReferenceExpression keyNameExpression = new CodePropertyReferenceExpression(configurationRowExpression, "IndexName"); this.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(Object[])), uniqueKeyExpression.VariableName, new CodePrimitiveExpression(null))); foreach (UniqueConstraintSchema uniqueConstraintSchema in uniqueConstraints) { // For each unique index on this table, a key is created that matches the key columns of the index selected by // the configuration. CodeConditionStatement ifConfiguration = new CodeConditionStatement(new CodeBinaryOperatorExpression(keyNameExpression, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(uniqueConstraintSchema.Name))); // If there are no foreign keys attached to the selected primary key, then the key value is taken directly from // the input parameters. ForeignKeyConstraintSchema foreignKeyConstraintSchema = uniqueConstraintSchema.ForeignKey; if (foreignKeyConstraintSchema == null) { // securityKey1 = new object[] { // objectRow4.ObjectId}; ifConfiguration.TrueStatements.Add(new CodeAssignStatement(uniqueKeyExpression, new CodeArgumentReferenceExpression(uniqueConstraintParameterItem.Name))); } else { // When there are foreign keys associated with the selected unique constraint, the foreign keys are resolved // using the key passed in as a parameter to this method. This is a recursive operation that digs through the // table hierarchy until a record is found that matches the key. CodeVariableReferenceExpression rootRowExpression = new CodeRandomVariableReferenceExpression(); ifConfiguration.TrueStatements.AddRange(new CodeResolveForeignKeyExpression(rootRowExpression, transactionExpression, new CodeArgumentReferenceExpression(uniqueConstraintParameterItem.Name), foreignKeyConstraintSchema, targetDataSet)); List <CodeExpression> keyItems = new List <CodeExpression>(); for (int columnIndex = 0; columnIndex < tableSchema.PrimaryKey.Columns.Length; columnIndex++) { keyItems.Add(new CodePropertyReferenceExpression(rootRowExpression, foreignKeyConstraintSchema.RelatedColumns[columnIndex].Name)); } ifConfiguration.TrueStatements.Add(new CodeAssignStatement(uniqueKeyExpression, new CodeArrayCreateExpression(new CodeGlobalTypeReference(typeof(Object)), keyItems.ToArray()))); } // } this.Add(ifConfiguration); } // // Use the index and the key specified by the configuration to find the record. // IObjectTreeIndex dataIndex2 = ((IObjectTreeIndex)(DataModel.ObjectTree.Indices[configurationRow4.IndexName])); // ObjectTreeRow objectTreeRow = dataIndex2.Find(objectTreeKey2); CodeTypeReference dataIndexType = new CodeTypeReference(String.Format("I{0}Index", tableSchema.Name)); CodeVariableReferenceExpression dataIndexExpression = new CodeRandomVariableReferenceExpression(); this.Add(new CodeVariableDeclarationStatement(dataIndexType, dataIndexExpression.VariableName, new CodeCastExpression(dataIndexType, new CodeIndexerExpression(new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(targetDataSet, String.Format("table{0}", tableSchema.Name)), "Indices"), keyNameExpression)))); this.Add(new CodeCheckIndexExistsStatement(dataIndexExpression, tableSchema, keyNameExpression)); this.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(String.Format("{0}Row", tableSchema.Name)), rowExpression.VariableName, new CodeMethodInvokeExpression(dataIndexExpression, "Find", uniqueKeyExpression))); } // if ((engineerRow == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::Teraque.RecordNotFoundFault("Attempt to access a Engineer record ({0}) that doesn\'t exist", engineerKey5)); // } // engineerRow.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(engineerRow); // if ((engineerRow.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::Teraque.RecordNotFoundFault("Attempt to access a Engineer record ({0}) that doesn\'t exist", engineerKey5)); // } this.Add(new CodeCheckRecordExistsStatement(tableSchema, rowExpression, uniqueKeyExpression)); this.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, rowExpression, tableSchema.DataModel)); this.Add(new CodeAddLockToTransactionExpression(transactionExpression, rowExpression)); this.Add(new CodeCheckRecordDetachedStatement(tableSchema, rowExpression, uniqueKeyExpression)); }
/// <summary> /// Creates the CodeDOM for a method to update a record in a table using transacted logic. /// </summary> /// <param name="tableSchema">A description of the table.</param> public UpdateMethod(TableSchema tableSchema) { // Create a matrix of parameters for this operation. UpdateParameterMatrix updateParameterMatrix = new UpdateParameterMatrix(tableSchema); // This is the key used to identify the record to be deleted. CodeArgumentReferenceExpression primaryKeyExpression = null; foreach (KeyValuePair <string, ExternalParameterItem> externalParamterPair in updateParameterMatrix.ExternalParameterItems) { if (externalParamterPair.Value is UniqueConstraintParameterItem) { primaryKeyExpression = new CodeArgumentReferenceExpression(externalParamterPair.Value.Name); } } // /// <summary> // /// Updates a Employee record. // /// </summary> // /// <param name="age">The optional value for the Age column.</param> // /// <param name="departmentId">The optional value for the DepartmentId column.</param> // /// <param name="employeeId">The required value for the EmployeeId column.</param> // /// <param name="raceCode">The optional value for the RaceCode column.</param> // /// <param name="rowVersion">Used for Optimistic Concurrency Checking.</param> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [FluidTrade.Core.ClaimsPrincipalPermission(global::System.Security.Permissions.SecurityAction.Demand, ClaimType=global::FluidTrade.Core.ClaimTypes.Update, Resource=global::FluidTrade.Core.Resources.Application)] // public void UpdateEmployee(object age, object departmentId, int employeeId, object raceCode, ref long rowVersion) { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Updates a {0} record.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in updateParameterMatrix.ExternalParameterItems) { this.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">{1}</param>", parameterPair.Value.Name, parameterPair.Value.Description), true)); } this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(System.ServiceModel.OperationBehaviorAttribute)), new CodeAttributeArgument("TransactionScopeRequired", new CodePrimitiveExpression(true)))); //AR FB 408 - Remove Claims requirement //this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(ClaimsPrincipalPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Security.Permissions.SecurityAction)), "Demand")), // new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Update")), // new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Name = string.Format("Update{0}", tableSchema.Name); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in updateParameterMatrix.ExternalParameterItems) { this.Parameters.Add(parameterPair.Value.CodeParameterDeclarationExpression); } // There is no way to find the existing record without a primary unique key. if (tableSchema.PrimaryKey == null) { return; } // // This provides a context for the middle tier transactions. // global::FluidTrade.Core.MiddleTierContext middleTierTransaction = global::FluidTrade.Core.MiddleTierContext.Current; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeCreateMiddleTierContextStatement(tableSchema.DataModel, transactionExpression)); // // This is the record that will be updated // global::System.Object[] employeeKey = new global::System.Object(new object[] { // employeeId}); // FluidTrade.UnitTest.Server.DataModel.EmployeeRow employeeRow = FluidTrade.UnitTest.Server.DataModel.Employee.FindByEmployeeId(employeeKey); // if ((employeeRow == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeKey)); // } CodeVariableReferenceExpression rowVariableExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(string.Format("{0}Row", tableSchema.Name)), rowVariableExpression.VariableName, new CodeFindByIndexExpression(tableSchema, primaryKeyExpression))); this.Statements.Add(new CodeCheckRecordExistsStatement(tableSchema, rowVariableExpression, primaryKeyExpression)); this.Statements.Add(new CodeAcquireRecordWriterLockExpression(transactionExpression, rowVariableExpression, tableSchema)); this.Statements.Add(new CodeAddLockToTransactionExpression(transactionExpression, rowVariableExpression)); // // This makes sure the record wasn't deleted between the time it was found and the time it was locked. // if ((employeeRow.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeId)); // } this.Statements.Add(new CodeCheckRecordDetachedStatement(tableSchema, rowVariableExpression, primaryKeyExpression)); // // The Optimistic Concurrency check allows only one client to update a record at a time. // if ((employeeRow.RowVersion != rowVersion)) { // throw new global::System.ServiceModel.FaultException<OptimisticConcurrencyFault>(new global::FluidTrade.Core.OptimisticConcurrencyFault("The Employee record (Employee) is busy. Please try again later.", employeeId)); // } this.Statements.Add(new CodeCheckConcurrencyStatement(tableSchema, rowVariableExpression, primaryKeyExpression)); // // This will provide the defaults elements of the Employee table that haven't changed. // if ((age == null)) { // age = employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.AgeColumn]; // } // if ((departmentId == null)) { // departmentId = employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.DepartmentIdColumn]; // } // if ((raceCode == null)) { // raceCode = employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.RaceCodeColumn]; // } bool isDefaultCommentEmitted = false; foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (!columnSchema.IsRowVersion) { if (!isDefaultCommentEmitted) { isDefaultCommentEmitted = true; } this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)), new CodeAssignStatement(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), string.Format("{0}Column", columnSchema.Name)))))); } } // // The current parent Department record is locked for reading for the duration of the transaction. // employeeRow.DepartmentRow.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(employeeRow.DepartmentRow); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((employeeRow.DepartmentRow.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId)); // } // // The current parent Object record is locked for reading for the duration of the transaction. // employeeRow.ObjectRow.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(employeeRow.ObjectRow); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((employeeRow.ObjectRow.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", employeeId)); // } // // The current parent Race record is locked for reading for the duration of the transaction. // if ((employeeRow.RaceRow != null)) { // employeeRow.RaceRow.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(employeeRow.RaceRow); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((employeeRow.RaceRow.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Race record ({0}) that doesn\'t exist", raceCode)); // } // } foreach (KeyValuePair <string, RelationSchema> relationPair in tableSchema.ParentRelations) { if (tableSchema != relationPair.Value.ParentTable) { // This is the table containing the parent record that is to be locked for the transaction. TableSchema parentTable = relationPair.Value.ParentTable; // The varible name for the parent row is decorated with the foreign key name thus making it unique. string parentRowName = string.Format("{0}RowBy{1}", CommonConversion.ToCamelCase(parentTable.Name), relationPair.Value.Name); string parentRowTypeName = string.Format("{0}Row", parentTable.Name); CodePropertyReferenceExpression parentRowExpression = relationPair.Value.IsDistinctPathToParent ? new CodePropertyReferenceExpression(rowVariableExpression, string.Format("{0}Row", parentTable.Name)) : new CodePropertyReferenceExpression(rowVariableExpression, string.Format("{0}RowBy{1}", parentTable.Name, relationPair.Value.Name)); // // The current parent Department record is locked for reading for the duration of the transaction. // employeeRow.DepartmentRow.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(employeeRow.DepartmentRow); CodeStatementCollection codeStatementCollection; if (relationPair.Value.ChildKeyConstraint.IsNullable) { CodeConditionStatement ifParentKeyExists = new CodeConditionStatement(new CodeBinaryOperatorExpression(parentRowExpression, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null))); codeStatementCollection = ifParentKeyExists.TrueStatements; this.Statements.Add(ifParentKeyExists); } else { codeStatementCollection = this.Statements; } codeStatementCollection.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, parentRowExpression, parentTable.DataModel)); codeStatementCollection.Add(new CodeAddLockToTransactionExpression(transactionExpression, parentRowExpression)); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((employeeRow.DepartmentRow.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId)); // } codeStatementCollection.Add(new CodeCheckRecordDetachedStatement(parentTable, parentRowExpression, new CodeKeyCreateExpression(relationPair.Value.ChildColumns))); } } // // Find the new proposed parent Department record if it is required for a foreign key constraint. // FluidTrade.UnitTest.Server.DataModel.DepartmentRow departmentRowByFK_Department_Employee = FluidTrade.UnitTest.Server.DataModel.Department.FindByDepartmentId(new object[] { // departmentId}); // if ((departmentRowByFK_Department_Employee == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId)); // } // departmentRowByFK_Department_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(departmentRowByFK_Department_Employee); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((departmentRowByFK_Department_Employee.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId)); // } // // Find the new proposed parent Object record if it is required for a foreign key constraint. // FluidTrade.UnitTest.Server.DataModel.ObjectRow objectRowByFK_Object_Employee = FluidTrade.UnitTest.Server.DataModel.Object.FindByObjectId(new object[] { // employeeId}); // if ((objectRowByFK_Object_Employee == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", employeeId)); // } // objectRowByFK_Object_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(objectRowByFK_Object_Employee); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((objectRowByFK_Object_Employee.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", employeeId)); // } // // Find the new proposed parent Race record if it is required for a foreign key constraint. // if ((raceCode != global::System.DBNull.Value)) { // FluidTrade.UnitTest.Server.DataModel.RaceRow raceRowByFK_Race_Employee = FluidTrade.UnitTest.Server.DataModel.Race.FindByRaceCode(new object[] { // raceCode}); // if ((raceRowByFK_Race_Employee == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Race record ({0}) that doesn\'t exist", raceCode)); // } // raceRowByFK_Race_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(raceRowByFK_Race_Employee); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((raceRowByFK_Race_Employee.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Race record ({0}) that doesn\'t exist", raceCode)); // } // } foreach (KeyValuePair <string, RelationSchema> relationPair in tableSchema.ParentRelations) { if (tableSchema != relationPair.Value.ParentTable) { // This is the table containing the parent record that is to be locked for the transaction. TableSchema parentTable = relationPair.Value.ParentTable; // The varible name for the parent row is decorated with the foreign key name thus making it unique. CodeVariableReferenceExpression parentRowVariableExpression = new CodeRandomVariableReferenceExpression(); CodeTypeReference parentRowType = new CodeTypeReference(string.Format("{0}Row", parentTable.Name)); // // Find the new proposed parent Race record if it is required for a foreign key constraint. // if ((raceCode != global::System.DBNull.Value)) { CodeExpression lockConditions = null; foreach (ColumnSchema columnSchema in relationPair.Value.ChildColumns) { if (columnSchema.IsNullable) { lockConditions = lockConditions == null ? new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.DBNull)), "Value")) : new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BitwiseAnd, lockConditions); } } CodeStatementCollection codeStatementCollection; if (lockConditions == null) { codeStatementCollection = this.Statements; } else { CodeConditionStatement ifParentKeyExists = new CodeConditionStatement(lockConditions); this.Statements.Add(ifParentKeyExists); codeStatementCollection = ifParentKeyExists.TrueStatements; } // global::System.Object[] raceRowByFK_Race_EmployeeKey = new object[] { // employeeId}); // FluidTrade.UnitTest.Server.DataModel.RaceRow raceRowByFK_Race_Employee = FluidTrade.UnitTest.Server.DataModel.Race.FindByRaceCode(new object[] { // raceCode}); // if ((raceRowByFK_Race_Employee == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Race record ({0}) that doesn\'t exist", raceCode)); // } CodeVariableReferenceExpression parentKeyExpression = new CodeRandomVariableReferenceExpression(); codeStatementCollection.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Object[])), parentKeyExpression.VariableName, new CodeKeyCreateExpression(relationPair.Value.ChildColumns))); if (tableSchema.PrimaryKey == null) { codeStatementCollection.Add(new CodeVariableDeclarationStatement(parentRowType, parentRowVariableExpression.VariableName, new CodeFindByRowExpression(parentTable, parentKeyExpression))); } else { codeStatementCollection.Add(new CodeVariableDeclarationStatement(parentRowType, parentRowVariableExpression.VariableName, new CodeFindByIndexExpression(parentTable, parentKeyExpression))); } codeStatementCollection.Add(new CodeCheckRecordExistsStatement(parentTable, parentRowVariableExpression, parentKeyExpression)); // raceRowByFK_Race_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(raceRowByFK_Race_Employee); codeStatementCollection.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, parentRowVariableExpression, parentTable.DataModel)); codeStatementCollection.Add(new CodeAddLockToTransactionExpression(transactionExpression, parentRowVariableExpression)); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((raceRowByFK_Race_Employee.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Race record ({0}) that doesn\'t exist", raceCode)); // } // } codeStatementCollection.Add(new CodeCheckRecordDetachedStatement(parentTable, parentRowVariableExpression, parentKeyExpression)); } } // // Update the Employee record in the ADO data model. // middleTierTransaction.AdoResourceManager.AddRecord(employeeRow); // try { // FluidTrade.UnitTest.Server.DataModel.Department.AcquireLock(); // FluidTrade.UnitTest.Server.DataModel.Employee.AcquireLock(); // FluidTrade.UnitTest.Server.DataModel.Object.AcquireLock(); // FluidTrade.UnitTest.Server.DataModel.Race.AcquireLock(); // employeeRow.BeginEdit(); // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.AgeColumn] = age; // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.DepartmentIdColumn] = departmentId; // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.RaceCodeColumn] = raceCode; // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.RowVersionColumn] = global::System.Threading.Interlocked.Increment(ref FluidTrade.UnitTest.Server.DataModel.masterRowVersion); // } // finally { // employeeRow.EndEdit(); // FluidTrade.UnitTest.Server.DataModel.Department.ReleaseLock(); // FluidTrade.UnitTest.Server.DataModel.Employee.ReleaseLock(); // FluidTrade.UnitTest.Server.DataModel.Object.ReleaseLock(); // FluidTrade.UnitTest.Server.DataModel.Race.ReleaseLock(); // } this.Statements.Add(new CodeAddRecordToTransactionExpression(transactionExpression, rowVariableExpression)); CodeTryCatchFinallyStatement tryFinallyStatement = new CodeTryCatchFinallyStatement(); tryFinallyStatement.TryStatements.Add( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "EnterWriteLock")); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(rowVariableExpression, "BeginEdit")); foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (columnSchema.IsAutoIncrement || columnSchema.IsPrimaryKey) { continue; } CodeExpression sourceExpression; if (columnSchema.IsRowVersion) { sourceExpression = sourceExpression = new CodeMethodInvokeExpression( new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(tableSchema.DataModel.Name), String.Format("{0}DataSet", CommonConversion.ToCamelCase(tableSchema.DataModel.Name))), "IncrementRowVersion"); } else { sourceExpression = new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)); } tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), string.Format("{0}Column", columnSchema.Name))), sourceExpression)); } tryFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(rowVariableExpression, "EndEdit")); tryFinallyStatement.FinallyStatements.Add( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "ExitWriteLock")); this.Statements.Add(tryFinallyStatement); // // Update the Employee record in the SQL data model. // global::System.Data.SqlClient.SqlCommand sqlCommand = new global::System.Data.SqlClient.SqlCommand("update \"Employee\" set \"Age\"=@age,\"DepartmentId\"=@departmentId,\"RaceCode\"=@raceCod" + // "e,\"RowVersion\"=@rowVersion,\"RowVersion\"=@rowVersion where \"EmployeeId\"=@employee" + // "Id", middleTierTransaction.SqlConnection); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@age", global::System.Data.SqlDbType.Int, 0, global::System.Data.ParameterDirection.Input, false, 0, 0, null, global::System.Data.DataRowVersion.Current, age)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@departmentId", global::System.Data.SqlDbType.Int, 0, global::System.Data.ParameterDirection.Input, false, 0, 0, null, global::System.Data.DataRowVersion.Current, departmentId)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@employeeId", global::System.Data.SqlDbType.Int, 0, global::System.Data.ParameterDirection.Input, false, 0, 0, null, global::System.Data.DataRowVersion.Current, employeeId)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@raceCode", global::System.Data.SqlDbType.Int, 0, global::System.Data.ParameterDirection.Input, false, 0, 0, null, global::System.Data.DataRowVersion.Current, raceCode)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@rowVersion", global::System.Data.SqlDbType.BigInt, 0, global::System.Data.ParameterDirection.Input, false, 0, 0, null, global::System.Data.DataRowVersion.Current, employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.RowVersionColumn])); // sqlCommand.ExecuteNonQuery(); if (tableSchema.IsPersistent) { CodeVariableReferenceExpression sqlCommandExpression = new CodeRandomVariableReferenceExpression(); string setList = string.Empty; foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (columnSchema.IsPersistent && !columnSchema.IsAutoIncrement) { setList += string.Format(setList == string.Empty ? "\"{0}\"=@{1}" : ",\"{0}\"=@{1}", columnSchema.Name, CommonConversion.ToCamelCase(columnSchema.Name)); } } string whereClause = string.Empty; foreach (ColumnSchema columnSchema in tableSchema.PrimaryKey.Columns) { whereClause += string.Format(whereClause == string.Empty ? "\"{0}\"=@key{0}" : " and \"{0}\"=@key{0}", columnSchema.Name); } string insertCommandText = string.Format("update \"{0}\" set {1} where {2}", tableSchema.Name, setList, whereClause); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlCommand)), sqlCommandExpression.VariableName, new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlCommand)), new CodePrimitiveExpression(insertCommandText), new CodePropertyReferenceExpression(transactionExpression, "SqlConnection")))); foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (columnSchema.IsPersistent) { string variableName = CommonConversion.ToCamelCase(columnSchema.Name); if (!columnSchema.IsAutoIncrement) { CodeExpression sourceExpression = columnSchema.IsRowVersion ? (CodeExpression) new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "RowVersionColumn")) : (CodeExpression) new CodeArgumentReferenceExpression(variableName); this.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(sqlCommandExpression, "Parameters"), "Add", new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlParameter)), new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.ParameterDirection)), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowVersion)), "Current"), sourceExpression))); } } } foreach (ColumnSchema columnSchema in tableSchema.PrimaryKey.Columns) { string variableName = string.Format("key{0}", columnSchema.Name); CodeExpression sourceExpression = new CodePropertyReferenceExpression(rowVariableExpression, columnSchema.Name); this.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(sqlCommandExpression, "Parameters"), "Add", new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlParameter)), new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.ParameterDirection)), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowVersion)), "Current"), sourceExpression))); } this.Statements.Add(new CodeMethodInvokeExpression(sqlCommandExpression, "ExecuteNonQuery")); } // DataModel.DestinationOrder.OnRowValidate(new DestinationOrderRowChangeEventArgs(pe9564f2717374e96a76d5222e2258784, System.Data.DataRowAction.Change)); this.Statements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "OnRowValidate", new CodeObjectCreateExpression( string.Format("{0}RowChangeEventArgs", tableSchema.Name), rowVariableExpression, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowAction)), "Change")))); // } }
/// <summary> /// Creates a method to handle moving the deleted records from the active data model to the deleted data model. /// </summary> /// <param name="schema">The data model schema.</param> public ReadMethod(DataModelSchema dataModelSchema) { // /// <summary> // /// Collects the set of modified records that will reconcile the client data model to the master data model. // /// </summary> // /// <param name="identifier">A unique identifier of an instance of the data.</param> // /// <param name="sequence">The sequence of the client data model.</param> // /// <returns>An array of records that will reconcile the client data model to the server.</returns> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [global::Teraque.ClaimsPermission(global::System.Security.Permissions.SecurityAction.Demand, ClaimType=global::Teraque.ClaimTypes.Read, Resource=global::Teraque.Resources.Application)] // public object[] Read(global::System.Guid identifier, long sequence) // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement("Collects the set of modified records that will reconcile the client data model to the master data model.", true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.Comments.Add(new CodeCommentStatement("<param name=\"identifier\">A unique identifier of an instance of the data.</param>", true)); this.Comments.Add(new CodeCommentStatement("<param name=\"sequence\">The sequence of the client data model.</param>", true)); this.Comments.Add(new CodeCommentStatement("<returns>An array of records that will reconcile the client data model to the server.</returns>", true)); this.CustomAttributes.Add( new CodeAttributeDeclaration( new CodeGlobalTypeReference(typeof(ClaimsPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(SecurityAction)), "Demand")), new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Read")), new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); this.Name = "Read"; this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.ReturnType = new CodeGlobalTypeReference(typeof(Object[])); this.Parameters.Add(new CodeParameterDeclarationExpression(new CodeGlobalTypeReference(typeof(Guid)), "identifier")); this.Parameters.Add(new CodeParameterDeclarationExpression(new CodeGlobalTypeReference(typeof(Int64)), "sequence")); // global::Teraque.OrganizationPrincipal c226 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); // if ((DataModel.tenantMap.ContainsKey(q3953.Organization) == false)) // { // throw new global::System.ServiceModel.FaultException<Teraque.TenantNotLoadedFault>(new global::Teraque.TenantNotLoadedFault(q3953.Organization)); // } this.Statements.Add( new CodeConditionStatement( new CodeBinaryOperatorExpression( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(dataModelSchema.Name), "tenantMap"), "ContainsKey", new CodePropertyReferenceExpression(organizationPrincipal, "Organization")), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(false)), new CodeStatement[] { new CodeThrowTenantNotLoadedExceptionStatement(new CodePropertyReferenceExpression(organizationPrincipal, "Organization")) })); // DataModelDataSet v227 = DataModel.tenantMap[c226.Tenant]; CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeTargetDataModelStatement(dataModelSchema, targetDataSet, organizationPrincipal)); // return i8562.Read(identifier, sequence); this.Statements.Add( new CodeMethodReturnStatement( new CodeMethodInvokeExpression(targetDataSet, "Read", new CodeArgumentReferenceExpression("identifier"), new CodeArgumentReferenceExpression("sequence")))); // } }
/// <summary> /// Generates a property to get a parent row. /// </summary> /// <param name="foreignKeyConstraintSchema">The foreign key that references the parent table.</param> public VoidConstructor(DataModelSchema dataModelSchema) { // /// <summary> // /// Creates the System.DataSet used to hold the data for the DataModel. // /// </summary> // internal DataModelDataSet(String connectionString) // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Creates the System.DataSet used to hold the data for the {0}.", dataModelSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.Attributes = MemberAttributes.Assembly; this.Parameters.Add(new CodeParameterDeclarationExpression(new CodeGlobalTypeReference(typeof(String)), "connectionString")); // this.connectionString = connectionString; this.Statements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "connectionString"), new CodeArgumentReferenceExpression("connectionString"))); // this.DataSetName = "DataModel"; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "DataSetName"), new CodePrimitiveExpression(dataModelSchema.Name))); // this.CaseSensitive = true; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "CaseSensitive"), new CodePrimitiveExpression(true))); // this.EnforceConstraints = true; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "EnforceConstraints"), new CodePrimitiveExpression(true))); // Create each of the tables and add them to the data set. for (int tableIndex = 0; tableIndex < dataModelSchema.Tables.Count; tableIndex++) { // The 'Tables' element of the schema is indexed by the name of the table normally. We're going to initialize the tables in the order of their // ordinals (order in which they were declared). This is done primarily to be able to give each table a 'Ordinal' number that is used during // transaction processing to quickly find the table (without using the table name). KeyValuePair <String, TableSchema> keyValuePair = Enumerable.ElementAt(dataModelSchema.Tables, tableIndex); // this.tableConfiguration = new ConfigurationDataTable(); this.Statements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), String.Format("table{0}", keyValuePair.Value.Name)), new CodeObjectCreateExpression(String.Format("{0}.{1}DataTable", keyValuePair.Value.DataModel.Name, keyValuePair.Value.Name)))); // this.tableConfiguration.Ordinal = 0; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), String.Format("table{0}", keyValuePair.Value.Name)), "Ordinal"), new CodePrimitiveExpression(tableIndex))); // this.Tables.Add(this.tableConfiguration); this.Statements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Tables"), "Add", new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), String.Format("table{0}", keyValuePair.Value.Name)))); } // global::System.Data.ForeignKeyConstraint foreignKeyConstraint4 = new global::System.Data.ForeignKeyConstraint("FK_AccountBase_Account", new global::System.Data.DataColumn[] { // this.tableAccountBase.AccountBaseIdColumn}, new global::System.Data.DataColumn[] { // this.tableAccount.AccountIdColumn}); // this.tableAccountBase.Constraints.Add(foreignKeyConstraint4); // global::System.Data.ForeignKeyConstraint foreignKeyConstraint5 = new global::System.Data.ForeignKeyConstraint("FK_LotHandling_Account", new global::System.Data.DataColumn[] { // this.tableLotHandling.LotHandlingIdColumn}, new global::System.Data.DataColumn[] { // this.tableAccount.LotHandlingIdColumn}); // this.tableLotHandling.Constraints.Add(foreignKeyConstraint5); foreach (KeyValuePair <String, TableSchema> tablePair in dataModelSchema.Tables) { foreach (KeyValuePair <String, ConstraintSchema> constraintPair in tablePair.Value.Constraints) { if (constraintPair.Value is ForeignKeyConstraintSchema) { // Construct a foreign key constraint described by this schema. ForeignKeyConstraintSchema foreignKeyConstraintSchema = constraintPair.Value as ForeignKeyConstraintSchema; // Refers to the foreign key constraint. CodeVariableReferenceExpression foreignKeyConstraintExpression = new CodeRandomVariableReferenceExpression(); // global::System.Data.ForeignKeyConstraint foreignKeyConstraint6 = new global::System.Data.ForeignKeyConstraint("FK_Country_AccountBase", new global::System.Data.DataColumn[] { // this.tableCountry.CountryIdColumn}, new global::System.Data.DataColumn[] { // this.tableAccountBase.CountryIdColumn}); this.Statements.Add( new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(ForeignKeyConstraint)), foreignKeyConstraintExpression.VariableName, new CodeForeignKeyConstraint(foreignKeyConstraintSchema))); this.Statements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), String.Format("table{0}", tablePair.Value.Name)), "Constraints"), "Add", foreignKeyConstraintExpression)); } } } // this.relationAccessRightAccessControl = new global::System.Data.DataRelation("FK_AccessRight_AccessControl", new global::System.Data.DataColumn[] { // this.tableAccessRight.AccessRightIdColumn}, new global::System.Data.DataColumn[] { // this.tableAccessControl.AccessRightIdColumn}, false); foreach (KeyValuePair <String, RelationSchema> relationPair in dataModelSchema.Relations) { // The name of the relation is decorated with the relation name when the relation between the child and the parent isn't unique. String relationName = relationPair.Value.IsDistinctPathToParent ? String.Format("relation{0}{1}", relationPair.Value.ParentTable.Name, relationPair.Value.ChildTable.Name) : String.Format("relation{0}{1}By{2}", relationPair.Value.ParentTable.Name, relationPair.Value.ChildTable.Name, relationPair.Value.Name); // this.relationRaceEmployee = new System.Data.DataRelation("FK_Race_Employee", new Teraque.Column[] { // Teraque.UnitTest.Server.DataModel.tableRace.RaceCodeColumn}, new Teraque.Column[] { // Teraque.UnitTest.Server.DataModel.tableEmployee.RaceCodeColumn}, false); // this.Relations.Add(Teraque.UnitTest.Server.DataModel.relationRaceEmployee); CodeExpression relationFieldExpression = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), relationName); this.Statements.Add(new CodeAssignStatement(relationFieldExpression, new CodeDataRelation(relationPair.Value))); this.Statements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Relations"), "Add", relationFieldExpression)); } // Teraque.UnitTest.Server.DataModel.Configuration.InitializeRelations(); // Teraque.UnitTest.Server.DataModel.Department.InitializeRelations(); foreach (KeyValuePair <string, TableSchema> keyValuePair in dataModelSchema.Tables) { this.Statements.Add( new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), String.Format("table{0}", keyValuePair.Value.Name)), "InitializeRelations")); } // this.dataLock = new global::System.Threading.ReaderWriterLockSlim(); this.Statements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "dataLock"), new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(ReaderWriterLockSlim))))); // this.identifier = global::System.Guid.NewGuid(); this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "identifier"), new CodeMethodInvokeExpression(new CodeGlobalTypeReferenceExpression(typeof(Guid)), "NewGuid"))); // this.rowVersion = 0; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "rowVersion"), new CodePrimitiveExpression(0L))); // this.transactionLog = new global::System.Collections.Generic.LinkedList<TransactionLogItem>(); this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "transactionLog"), new CodeObjectCreateExpression(new CodeTypeReference("global::System.Collections.Generic.LinkedList<TransactionLogItem>")))); // this.transactionLogBatchSize = 10000; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "transactionLogBatchSize"), new CodePrimitiveExpression(10000))); // this.logCompressionInterval = global::System.TimeSpan.FromSeconds(10); this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "logCompressionInterval"), new CodeMethodInvokeExpression( new CodeGlobalTypeReferenceExpression(typeof(TimeSpan)), "FromSeconds", new CodePrimitiveExpression(10)))); // this.transactionLogItemAge = global::System.TimeSpan.FromSeconds(60); this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "transactionLogItemAge"), new CodeMethodInvokeExpression( new CodeGlobalTypeReferenceExpression(typeof(TimeSpan)), "FromSeconds", new CodePrimitiveExpression(60)))); // this.transactionLogLock = new global::System.Threading.ReaderWriterLockSlim(); this.Statements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "transactionLogLock"), new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(ReaderWriterLockSlim))))); // this.compressorThread = new global::System.Threading.Thread(this.CompressLog); this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "compressorThread"), new CodeObjectCreateExpression( new CodeGlobalTypeReference(typeof(Thread)), new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), "CompressLog")))); // this.compressorThread.IsBackground = true; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "compressorThread"), "IsBackground"), new CodePrimitiveExpression(true))); // this.compressorThread.Name = "Transaction Log Compressor"; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "compressorThread"), "Name"), new CodePrimitiveExpression("Transaction Log Compressor"))); // this.compressorThread.Priority = global::System.Threading.ThreadPriority.Lowest; this.Statements.Add( new CodeAssignStatement( new CodePropertyReferenceExpression( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "compressorThread"), "Priority"), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ThreadPriority)), "Lowest"))); // this.compressorThread.Start(); this.Statements.Add( new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "compressorThread"), "Start")); // } // this.LoadData(); this.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "LoadData")); // } }
/// <summary> /// Creates a method that loads records into the database from an external source. /// </summary> /// <param name="tableSchema">The schema used to describe the table.</param> public StoreMethod(TableSchema tableSchema) { // This shreds the list of parameters up into a metadata stucture that is helpful in extracting ordinary parameters // from those that need to be found in other tables using external identifiers. CreateExParameterMatrix createParameterMatrix = new CreateExParameterMatrix(tableSchema); // /// <summary> // /// Loads a record into the Department table from an external source. // /// </summary> // /// <param name="age">The required value for the Age column.</param> // /// <param name="configurationId">Selects a configuration of unique indices used to resolve external identifiers.</param> // /// <param name="genderKey">A required unique key for the parent Gender record.</param> // /// <param name="objectKey">A required unique key for the parent Object record.</param> // /// <param name="unionKey">A required unique key for the parent Union record.</param> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [global::Teraque.ClaimsPrincipalPermission(global::System.Security.Permissions.SecurityAction.Demand, ClaimType=global::Teraque.ClaimTypes.Create, Resource=global::Teraque.Resources.Application)] // public void StoreEmployee(int age, string configurationId, object[] genderKey, object[] objectKey, object[] unionKey) { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Stores a record in the {0} table.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.Add( new CodeAttributeDeclaration( new CodeGlobalTypeReference(typeof(OperationBehaviorAttribute)), new CodeAttributeArgument("TransactionScopeRequired", new CodePrimitiveExpression(true)))); this.CustomAttributes.Add( new CodeAttributeDeclaration( new CodeGlobalTypeReference(typeof(ClaimsPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(SecurityAction)), "Demand")), new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Create")), new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { this.Comments.Add(new CodeCommentStatement(String.Format("<param name=\"{0}\">{1}</param>", parameterPair.Value.Name, parameterPair.Value.Description), true)); } this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Name = String.Format("Store{0}", tableSchema.Name); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { this.Parameters.Add(parameterPair.Value.CodeParameterDeclarationExpression); } // global::Teraque.OrganizationPrincipal c226 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); // if ((DataModel.tenantMap.ContainsKey(q3953.Organization) == false)) // { // throw new global::System.ServiceModel.FaultException<Teraque.TenantNotLoadedFault>(new global::Teraque.TenantNotLoadedFault(q3953.Organization)); // } this.Statements.Add( new CodeConditionStatement( new CodeBinaryOperatorExpression( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModelSchema.Name), "tenantMap"), "ContainsKey", new CodePropertyReferenceExpression(organizationPrincipal, "Organization")), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(false)), new CodeStatement[] { new CodeThrowTenantNotLoadedExceptionStatement(new CodePropertyReferenceExpression(organizationPrincipal, "Organization")) })); // DataModelTransaction o1881 = DataModel.CurrentTransaction; // TenantTarget d1882 = o1881.tenantDataSet; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeCreateTransactionStatement(tableSchema.DataModel, transactionExpression)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.Statements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("Tenant{0}", tableSchema.DataModelSchema.Name)), targetDataSet.VariableName, new CodeFieldReferenceExpression(transactionExpression, "tenantDataSet"))); // This will resolve the external identifiers that relate to foreign tables. The main idea is to map elements from foreign rows into parameters that // can be used to call the internal methods. foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { // This will recurse into the foreign key relations that use external identifiers and create code to resolve the // variables using the external record. if (parameterPair.Value is ForeignKeyConstraintParameterItem) { this.Statements.AddRange(new CodeResolveExternalVariableStatements(tableSchema, transactionExpression, parameterPair.Value as ForeignKeyConstraintParameterItem, targetDataSet)); } } // All the external identifiers have been resolved. Now it is time to see if the record exists or if it has to be created. Finding the record requires // a unique index. If there are more than one unique index, a decision needs to be made as to which one should be used. The configuration will drive // that decision. If there is only one unique constraint, then the decision doesn't need to be made. UniqueConstraintSchema[] uniqueConstraints = tableSchema.UniqueConstraintSchemas; // Optimized code is provided when there is only one unique constraint on a table. This saves the database administrator from having to configure every // single table in the data model with a description of the unique index that is to be used when finding a row in that table. If there is more than one // unique constraint on a table, a value will need to be provided in the configuration to tell the loader which one to use. if (uniqueConstraints.Length == 1) { // object[] i1650 = new object[] { // configurationId, // relationName}; this.Statements.Add( new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(Object[])), createParameterMatrix.UniqueKeyExpression.VariableName, new CodeKeyCreateExpression(createParameterMatrix.CreateKey(uniqueConstraints[0])))); // ConfigurationRow d1649 = f1652.tableConfiguration.ConfigurationKey.Find(i1650); this.Statements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("{0}Row", tableSchema.Name)), createParameterMatrix.RowExpression.VariableName, new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(targetDataSet, String.Format("table{0}", tableSchema.Name)), uniqueConstraints[0].Name), "Find", createParameterMatrix.UniqueKeyExpression))); } else { // object[] g2835 = new object[] { // configurationId, // "Country"}; CodeVariableReferenceExpression configurationKeyExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add( new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(Object[])), configurationKeyExpression.VariableName, new CodeKeyCreateExpression(new CodeArgumentReferenceExpression("configurationId"), new CodePrimitiveExpression(tableSchema.Name)))); // ConfigurationRow t2836 = a2833.tableConfiguration.ConfigurationKey.Find(g2835); CodeVariableReferenceExpression configurationRowExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference("ConfigurationRow"), configurationRowExpression.VariableName, new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(targetDataSet, "tableConfiguration"), "ConfigurationKey"), "Find", configurationKeyExpression))); // if ((t2836 == null)) // { // throw new global::System.ServiceModel.FaultException<Teraque.RecordNotFoundFault>(new global::Teraque.RecordNotFoundFault("Configuration", g2835)); // } TableSchema configurationTableSchema = tableSchema.DataModel.Tables["Configuration"]; this.Statements.Add(new CodeCheckRecordExistsStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); // t2836.AcquireReaderLock(f2834.TransactionId, DataModel.lockTimeout); this.Statements.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, configurationRowExpression, tableSchema.DataModel)); // f2834.AddLock(t2836); this.Statements.Add(new CodeAddLockToTransactionExpression(transactionExpression, configurationRowExpression)); // if ((t2836.RowState == global::System.Data.DataRowState.Detached)) // { // throw new global::System.ServiceModel.FaultException<Teraque.RecordNotFoundFault>(new global::Teraque.RecordNotFoundFault("Configuration", g2835)); // } this.Statements.Add(new CodeCheckRecordDetachedStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); // object[] a2831 = null; this.Statements.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(Object[])), createParameterMatrix.UniqueKeyExpression.VariableName, new CodePrimitiveExpression(null))); // if ((t2836.IndexName == "CountryKey")) // { // a2831 = new object[] { // countryId}; // } // if ((t2836.IndexName == "CountryKeyExternalId0")) // { // a2831 = new object[] { // externalId0}; // } // if ((t2836.IndexName == "CountryKeyExternalId1")) // { // a2831 = new object[] { // externalId1}; // } CodePropertyReferenceExpression indexNameExpression = new CodePropertyReferenceExpression(configurationRowExpression, "IndexName"); foreach (UniqueConstraintSchema uniqueConstraintSchema in uniqueConstraints) { CodeConditionStatement ifConfiguration = new CodeConditionStatement( new CodeBinaryOperatorExpression(indexNameExpression, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(uniqueConstraintSchema.Name))); ifConfiguration.TrueStatements.Add( new CodeAssignStatement(createParameterMatrix.UniqueKeyExpression, new CodeKeyCreateExpression(createParameterMatrix.CreateKey(uniqueConstraintSchema)))); this.Statements.Add(ifConfiguration); } // ICountryIndex v2837 = ((ICountryIndex)(DataModel.Country.Indices[t2836.IndexName])); CodeTypeReference dataIndexType = new CodeTypeReference(String.Format("I{0}Index", tableSchema.Name)); CodeVariableReferenceExpression dataIndexExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add( new CodeVariableDeclarationStatement( dataIndexType, dataIndexExpression.VariableName, new CodeCastExpression( dataIndexType, new CodeIndexerExpression( new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(targetDataSet, String.Format("table{0}", tableSchema.Name)), "Indices"), indexNameExpression)))); // if ((v2837 == null)) // { // throw new global::System.ServiceModel.FaultException<Teraque.IndexNotFoundFault>(new global::Teraque.IndexNotFoundFault("Country", t2836.IndexName)); // } this.Statements.Add(new CodeCheckIndexExistsStatement(dataIndexExpression, tableSchema, indexNameExpression)); // CountryRow g2830 = v2837.Find(a2831); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(String.Format("{0}Row", tableSchema.Name)), createParameterMatrix.RowExpression.VariableName, new CodeMethodInvokeExpression(dataIndexExpression, "Find", createParameterMatrix.UniqueKeyExpression))); } // // Create the record if it doesn't exist, update if it does. // if ((objectTreeRow == null)) // { // if ((objectTreeId == global::System.Guid.Empty)) // { // objectTreeId = global::System.Guid.NewGuid(); // } // this.CreateObjectTree(childId, objectTreeId, parentId, out rowVersion); // } CodeConditionStatement ifRowIsNew = new CodeConditionStatement(new CodeBinaryOperatorExpression(createParameterMatrix.RowExpression, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null))); foreach (KeyValuePair <string, InternalParameterItem> internalParameterPair in createParameterMatrix.CreateParameterItems) { InternalParameterItem internalParameterItem = internalParameterPair.Value; if (internalParameterItem.ColumnSchema.DataType == typeof(Guid) && internalParameterItem.ColumnSchema.IsOrphan) { CodeConditionStatement ifGuidNull = internalParameterItem.ColumnSchema.IsNullable || internalParameterItem.ColumnSchema.DefaultValue != DBNull.Value ? new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BooleanAnd, new CodeBinaryOperatorExpression(new CodeCastExpression(new CodeGlobalTypeReference(internalParameterItem.ColumnSchema.DataType), new CodeVariableReferenceExpression(internalParameterItem.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Guid)), "Empty")))) : new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Guid)), "Empty"))); ifGuidNull.TrueStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(internalParameterItem.Name), new CodeMethodInvokeExpression(new CodeGlobalTypeReferenceExpression(typeof(Guid)), "NewGuid"))); ifRowIsNew.TrueStatements.Add(ifGuidNull); } } ifRowIsNew.TrueStatements.Add( new CodeMethodInvokeExpression(targetDataSet, String.Format("Create{0}", tableSchema.Name), createParameterMatrix.CreateParameterExpressions)); // else // { // objectTreeRow.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(objectTreeRow); // if ((objectTreeRow.RowState == global::System.Data.DataRowState.Detached)) // { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::Teraque.RecordNotFoundFault("Attempt to access a ObjectTree record ({0}) that doesn\'t exist", objectTreeKey2)); // } // rowVersion = objectTreeRow.RowVersion; // this.UpdateObjectTree(childId, objectTreeId, parentId, ref rowVersion); // } ifRowIsNew.FalseStatements.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, createParameterMatrix.RowExpression, tableSchema.DataModel)); ifRowIsNew.FalseStatements.Add(new CodeAddLockToTransactionExpression(transactionExpression, createParameterMatrix.RowExpression)); ifRowIsNew.FalseStatements.Add(new CodeCheckRecordDetachedStatement(tableSchema, createParameterMatrix.RowExpression, createParameterMatrix.UniqueKeyExpression)); foreach (KeyValuePair <string, InternalParameterItem> internalParameterPair in createParameterMatrix.CreateParameterItems) { InternalParameterItem internalParameterItem = internalParameterPair.Value; if (internalParameterItem.ColumnSchema.DataType == typeof(Guid) && internalParameterItem.ColumnSchema.IsOrphan) { CodeConditionStatement ifGuidNull = internalParameterItem.ColumnSchema.IsNullable || internalParameterItem.ColumnSchema.DefaultValue != DBNull.Value ? new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BooleanAnd, new CodeBinaryOperatorExpression(new CodeCastExpression(new CodeGlobalTypeReference(internalParameterItem.ColumnSchema.DataType), new CodeVariableReferenceExpression(internalParameterItem.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Guid)), "Empty")))) : new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Guid)), "Empty"))); ifGuidNull.TrueStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(internalParameterItem.Name), new CodePropertyReferenceExpression(createParameterMatrix.RowExpression, internalParameterItem.ColumnSchema.Name))); ifRowIsNew.FalseStatements.Add(ifGuidNull); } } ifRowIsNew.FalseStatements.Add( new CodeMethodInvokeExpression(targetDataSet, String.Format("Update{0}", tableSchema.Name), createParameterMatrix.UpdateParameterExpressions)); // } this.Statements.Add(ifRowIsNew); }
/// <summary> /// Generates a method to get a list of child rows. /// </summary> /// <param name="relationSchema">A description of the relation between two tables.</param> public GetChildRowsMethod(RelationSchema relationSchema) { // These variables are used to construct the method. TableSchema childTable = relationSchema.ChildTable; TableSchema parentTable = relationSchema.ParentTable; string rowTypeName = String.Format("{0}Row", childTable.Name); string tableFieldName = String.Format("table{0}", parentTable.Name); string childRowTypeName = String.Format("{0}Row", relationSchema.ChildTable.Name); // /// <summary> // /// Gets the children rows in the AccountGroup table. // /// </summary> // public AccountGroupRow[] GetAccountGroupRows() // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Gets the children rows in the {0} table.", relationSchema.ChildTable.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.ReturnType = new CodeTypeReference(childRowTypeName, 1); this.Name = relationSchema.IsDistinctPathToChild ? String.Format("Get{0}s", childRowTypeName) : String.Format("Get{0}sBy{1}", childRowTypeName, relationSchema.Name); string relationName = relationSchema.IsDistinctPathToChild ? String.Format("{0}{1}Relation", relationSchema.ParentTable.Name, relationSchema.ChildTable.Name) : String.Format("{0}{1}By{2}Relation", relationSchema.ParentTable.Name, relationSchema.ChildTable.Name, relationSchema.Name); // DataModelTransaction p7519 = DataModel.CurrentTransaction; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("{0}Transaction", parentTable.DataModel.Name)), transactionExpression.VariableName, new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(parentTable.DataModel.Name), "CurrentTransaction"))); // if ((this.IsLockHeld(p7519.TransactionId) == false)) // { // throw new global::System.ServiceModel.FaultException<Teraque.SynchronizationLockFault>(new global::Teraque.SynchronizationLockFault("AccountBase")); // } this.Statements.AddRange(new CodeCheckReaderLockHeldStatements(new CodeThisReferenceExpression(), relationSchema.ParentTable, transactionExpression)); // try // { CodeTryCatchFinallyStatement tryCatchFinallyStatement = new CodeTryCatchFinallyStatement(); // ((TenantDataModel)(this.Table.DataSet)).dataLock.EnterReadLock(); tryCatchFinallyStatement.TryStatements.Add( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression( new CodeCastExpression( new CodeTypeReference(String.Format("Tenant{0}", parentTable.DataModel.Name)), new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Table"), "DataSet")), "dataLock"), "EnterReadLock")); // return ((AccountGroupRow[])(this.GetChildRows(this.tableAccountBase.AccountBaseAccountGroupRelation))); tryCatchFinallyStatement.TryStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(new CodeTypeReference(childRowTypeName, 1), new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "GetChildRows", new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), tableFieldName), relationName))))); // } // finally // { // ((TenantTarget)(this.Table.DataSet)).dataLock.ExitReadLock(); tryCatchFinallyStatement.FinallyStatements.Add( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression( new CodeCastExpression( new CodeTypeReference(String.Format("Tenant{0}", parentTable.DataModelSchema.Name)), new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Table"), "DataSet")), "dataLock"), "ExitReadLock")); this.Statements.Add(tryCatchFinallyStatement); // } // } }
/// <summary> /// Creates a method that loads records into the database from an external source. /// </summary> /// <param name="tableSchema">The schema used to describe the table.</param> public CreateExMethod(TableSchema tableSchema) { // This shreds the list of parameters up into a metadata stucture that is helpful in extracting ordinary parameters // from those that need to be found in other tables using external identifiers. CreateExParameterMatrix createParameterMatrix = new CreateExParameterMatrix(tableSchema); // /// <summary> // /// Loads a record into the Department table from an external source. // /// </summary> // /// <param name="age">The required value for the Age column.</param> // /// <param name="configurationId">Selects a configuration of unique indices used to resolve external identifiers.</param> // /// <param name="genderKey">A required unique key for the parent Gender record.</param> // /// <param name="objectKey">A required unique key for the parent Object record.</param> // /// <param name="unionKey">A required unique key for the parent Union record.</param> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [global::FluidTrade.Core.ClaimsPrincipalPermission(global::System.Security.Permissions.SecurityAction.Demand, ClaimType=global::FluidTrade.Core.ClaimTypes.Create, Resource=global::FluidTrade.Core.Resources.Application)] // public void CreateEmployeeEx(int age, string configurationId, object[] genderKey, object[] objectKey, object[] unionKey) { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Loads a record into the {0} table from an external source.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(System.ServiceModel.OperationBehaviorAttribute)), new CodeAttributeArgument("TransactionScopeRequired", new CodePrimitiveExpression(true)))); //AR FB 408 - Remove Claims requirement //this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(ClaimsPrincipalPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Security.Permissions.SecurityAction)), "Demand")), // new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Create")), // new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { this.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">{1}</param>", parameterPair.Value.Name, parameterPair.Value.Description), true)); } this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Name = string.Format("Create{0}Ex", tableSchema.Name); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { this.Parameters.Add(parameterPair.Value.CodeParameterDeclarationExpression); } // // This provides a context for the middle tier transactions. // global::FluidTrade.Core.MiddleTierContext middleTierTransaction = global::FluidTrade.Core.MiddleTierContext.Current; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeCreateMiddleTierContextStatement(tableSchema.DataModel, transactionExpression)); // This will resolve the external identifiers that relate to foreign tables. The main idea is to map elements from // foreign rows into parameters that can be used to call the internal methods. foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { // This will recurse into the foreign key relations that use external identifiers and create code to resolve the // variables using the external record. if (parameterPair.Value is ForeignKeyConstraintParameterItem) { this.Statements.AddRange(new CodeResolveExternalVariableStatements(tableSchema, transactionExpression, parameterPair.Value as ForeignKeyConstraintParameterItem)); } } // All the external identifiers have been resolved. Now it is time to see if the record exists or if it has to be // created. Finding the record requires a unique index. If there are more than one unique index, a decision needs to // be made as to which one should be used. The configuration will drive that decision. If there is only one unique // constraint, then the decision doesn't need to be made. UniqueConstraintSchema[] uniqueConstraints = tableSchema.UniqueConstraintSchemas; // Optimized code is provided when there is only one unique constraint on a table. This saves the database // administrator from having to configure every single table in the data model with a description of the unique index // that is to be used when finding a row in that table. If there is more than one unique constraint on a table, a // value will need to be provided in the configuration to tell the loader which one to use. if (uniqueConstraints.Length == 1) { // // Find the record using the only index available. // object[] configurationKey0 = new object[] { // configurationId, // relationName}; // ConfigurationRow configurationRow = DataModel.Configuration.ConfigurationKey.Find(configurationKey0); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Object[])), createParameterMatrix.UniqueKeyExpression.VariableName, new CodeKeyCreateExpression(createParameterMatrix.CreateKey(uniqueConstraints[0])))); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(string.Format("{0}Row", tableSchema.Name)), createParameterMatrix.RowExpression.VariableName, new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), uniqueConstraints[0].Name), "Find", createParameterMatrix.UniqueKeyExpression))); } else { // // This will find and lock the configuration row that selects the unique constraint for this table. // object[] configurationKey0 = new object[] { // configurationId, // "Gender"}; // ConfigurationRow configurationRow0 = DataModel.Configuration.ConfigurationKey.Find(configurationKey0); // if ((configurationRow0 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey0)); // } // configurationRow0.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(configurationRow0); // if ((configurationRow0.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey0)); // } CodeVariableReferenceExpression configurationKeyExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Object[])), configurationKeyExpression.VariableName, new CodeKeyCreateExpression(new CodeArgumentReferenceExpression("configurationId"), new CodePrimitiveExpression(tableSchema.Name)))); CodeVariableReferenceExpression configurationRowExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference("ConfigurationRow"), configurationRowExpression.VariableName, new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "Configuration"), "ConfigurationKey"), "Find", configurationKeyExpression))); TableSchema configurationTableSchema = tableSchema.DataModel.Tables["Configuration"]; this.Statements.Add(new CodeCheckRecordExistsStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); this.Statements.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, configurationRowExpression, tableSchema.DataModel)); this.Statements.Add(new CodeAddLockToTransactionExpression(transactionExpression, configurationRowExpression)); this.Statements.Add(new CodeCheckRecordDetachedStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); // object[] genderKey1 = null; // if ((configurationRow0.IndexName == "GenderKey")) { // genderKey1 = new object[] { // genderCode}; // } // if ((configurationRow0.IndexName == "GenderKeyExternalId0")) { // genderKey1 = new object[] { // externalId0}; // } this.Statements.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Object[])), createParameterMatrix.UniqueKeyExpression.VariableName, new CodePrimitiveExpression(null))); CodePropertyReferenceExpression indexNameExpression = new CodePropertyReferenceExpression(configurationRowExpression, "IndexName"); foreach (UniqueConstraintSchema uniqueConstraintSchema in uniqueConstraints) { CodeConditionStatement ifConfiguration = new CodeConditionStatement(new CodeBinaryOperatorExpression(indexNameExpression, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(uniqueConstraintSchema.Name))); ifConfiguration.TrueStatements.Add(new CodeAssignStatement(createParameterMatrix.UniqueKeyExpression, new CodeKeyCreateExpression(createParameterMatrix.CreateKey(uniqueConstraintSchema)))); this.Statements.Add(ifConfiguration); } // // Use the index and the key specified by the configuration to find the record. // IGenderIndex dataIndex0 = ((IGenderIndex)(DataModel.Gender.Indices[configurationRow0.IndexName])); // GenderRow genderRow = dataIndex0.Find(genderKey1); CodeTypeReference dataIndexType = new CodeTypeReference(string.Format("I{0}Index", tableSchema.Name)); CodeVariableReferenceExpression dataIndexExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeVariableDeclarationStatement(dataIndexType, dataIndexExpression.VariableName, new CodeCastExpression(dataIndexType, new CodeIndexerExpression(new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "Indices"), indexNameExpression)))); this.Statements.Add(new CodeCheckIndexExistsStatement(dataIndexExpression, tableSchema, indexNameExpression)); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(string.Format("{0}Row", tableSchema.Name)), createParameterMatrix.RowExpression.VariableName, new CodeMethodInvokeExpression(dataIndexExpression, "Find", createParameterMatrix.UniqueKeyExpression))); } // // Create the record if it doesn't exist, update if it does. // if ((objectTreeRow == null)) // { // if ((objectTreeId == global::System.Guid.Empty)) // { // objectTreeId = global::System.Guid.NewGuid(); // } // this.CreateObjectTree(childId, objectTreeId, parentId, out rowVersion); // } CodeConditionStatement ifRowIsNew = new CodeConditionStatement(new CodeBinaryOperatorExpression(createParameterMatrix.RowExpression, CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null))); foreach (KeyValuePair <string, InternalParameterItem> internalParameterPair in createParameterMatrix.CreateParameterItems) { InternalParameterItem internalParameterItem = internalParameterPair.Value; if (internalParameterItem.ColumnSchema.DataType == typeof(System.Guid) && internalParameterItem.ColumnSchema.IsOrphan) { CodeConditionStatement ifGuidNull = internalParameterItem.ColumnSchema.IsNullable || internalParameterItem.ColumnSchema.DefaultValue != DBNull.Value ? new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BooleanAnd, new CodeBinaryOperatorExpression(new CodeCastExpression(new CodeGlobalTypeReference(internalParameterItem.ColumnSchema.DataType), new CodeVariableReferenceExpression(internalParameterItem.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Guid)), "Empty")))) : new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Guid)), "Empty"))); ifGuidNull.TrueStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(internalParameterItem.Name), new CodeMethodInvokeExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Guid)), "NewGuid"))); ifRowIsNew.TrueStatements.Add(ifGuidNull); } } ifRowIsNew.TrueStatements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), string.Format("Create{0}", tableSchema.Name), createParameterMatrix.CreateParameterExpressions)); // else // { // objectTreeRow.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(objectTreeRow); // if ((objectTreeRow.RowState == global::System.Data.DataRowState.Detached)) // { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a ObjectTree record ({0}) that doesn\'t exist", objectTreeKey2)); // } // rowVersion = objectTreeRow.RowVersion; // this.UpdateObjectTree(childId, objectTreeId, parentId, ref rowVersion); // } ifRowIsNew.FalseStatements.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, createParameterMatrix.RowExpression, tableSchema.DataModel)); ifRowIsNew.FalseStatements.Add(new CodeAddLockToTransactionExpression(transactionExpression, createParameterMatrix.RowExpression)); ifRowIsNew.FalseStatements.Add(new CodeCheckRecordDetachedStatement(tableSchema, createParameterMatrix.RowExpression, createParameterMatrix.UniqueKeyExpression)); foreach (KeyValuePair <string, InternalParameterItem> internalParameterPair in createParameterMatrix.CreateParameterItems) { InternalParameterItem internalParameterItem = internalParameterPair.Value; if (internalParameterItem.ColumnSchema.DataType == typeof(System.Guid) && internalParameterItem.ColumnSchema.IsOrphan) { CodeConditionStatement ifGuidNull = internalParameterItem.ColumnSchema.IsNullable || internalParameterItem.ColumnSchema.DefaultValue != DBNull.Value ? new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BooleanAnd, new CodeBinaryOperatorExpression(new CodeCastExpression(new CodeGlobalTypeReference(internalParameterItem.ColumnSchema.DataType), new CodeVariableReferenceExpression(internalParameterItem.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Guid)), "Empty")))) : new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(internalParameterItem.Name), CodeBinaryOperatorType.IdentityEquality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Guid)), "Empty"))); ifGuidNull.TrueStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(internalParameterItem.Name), new CodePropertyReferenceExpression(createParameterMatrix.RowExpression, internalParameterItem.ColumnSchema.Name))); ifRowIsNew.FalseStatements.Add(ifGuidNull); } } ifRowIsNew.FalseStatements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), string.Format("Update{0}", tableSchema.Name), createParameterMatrix.UpdateParameterExpressions)); // } this.Statements.Add(ifRowIsNew); }
/// <summary> /// Creates a method that loads records into the database from an external source. /// </summary> /// <param name="tableSchema">The schema used to describe the table.</param> public DestroyMethod(TableSchema tableSchema) { // This shreds the list of parameters up into a metadata stucture that is helpful in extracting ordinary parameters // from those that need to be found in other tables using external identifiers. DestroyExParameterMatrix destroyParameterMatrix = new DestroyExParameterMatrix(tableSchema); // /// <summary> // /// Loads a record into the Department table from an external source. // /// </summary> // /// <param name="configurationId">Selects a configuration of unique indices used to resolve external identifiers.</param> // /// <param name="employeeKey">An optional unique key for the parent Employee record.</param> // /// <param name="managerKey">An optional unique key for the parent Manager record.</param> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [global::Teraque.ClaimsPrincipalPermission(global::System.Security.Permissions.SecurityAction.Demand, ClaimType=global::Teraque.ClaimTypes.Create, Resource=global::Teraque.Resources.Application)] // public void DestroyEngineerEx(string configurationId, object[] employeeKey, object[] managerKey) { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Loads a record into the Department table from an external source.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(OperationBehaviorAttribute)), new CodeAttributeArgument("TransactionScopeRequired", new CodePrimitiveExpression(true)))); this.CustomAttributes.Add( new CodeAttributeDeclaration( new CodeGlobalTypeReference(typeof(ClaimsPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(SecurityAction)), "Demand")), new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Create")), new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { this.Comments.Add(new CodeCommentStatement(String.Format("<param name=\"{0}\">{1}</param>", parameterPair.Value.Name, parameterPair.Value.Description), true)); } this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Name = String.Format("Destroy{0}", tableSchema.Name); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { this.Parameters.Add(parameterPair.Value.CodeParameterDeclarationExpression); } // global::Teraque.OrganizationPrincipal c226 = ((Teraque.OrganizationPrincipal)(global::System.Threading.Thread.CurrentPrincipal)); CodeVariableReferenceExpression organizationPrincipal = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeOrganizationPrincipalExpression(organizationPrincipal)); // if ((DataModel.tenantMap.ContainsKey(q3953.Organization) == false)) // { // throw new global::System.ServiceModel.FaultException<Teraque.TenantNotLoadedFault>(new global::Teraque.TenantNotLoadedFault(q3953.Organization)); // } this.Statements.Add( new CodeConditionStatement( new CodeBinaryOperatorExpression( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModelSchema.Name), "tenantMap"), "ContainsKey", new CodePropertyReferenceExpression(organizationPrincipal, "Organization")), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(false)), new CodeStatement[] { new CodeThrowTenantNotLoadedExceptionStatement(new CodePropertyReferenceExpression(organizationPrincipal, "Organization")) })); // DataModelTransaction o1881 = DataModel.CurrentTransaction; // TenantTarget d1882 = o1881.tenantDataSet; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeCreateTransactionStatement(tableSchema.DataModel, transactionExpression)); CodeVariableReferenceExpression targetDataSet = new CodeRandomVariableReferenceExpression(); this.Statements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("Tenant{0}", tableSchema.DataModelSchema.Name)), targetDataSet.VariableName, new CodeFieldReferenceExpression(transactionExpression, "tenantDataSet"))); // This will resolve the external identifiers and the build the primary key for the target record. The main idea is to // map elements from foreign rows into parameters that can be used to call the internal methods. foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in destroyParameterMatrix.ExternalParameterItems) { // Every internal update method requires a primary key. The external methods do not have this requirement and can // use any unique key. The translation between the external unique key and the internal primary key is created // here. if (parameterPair.Value is UniqueConstraintParameterItem) { this.Statements.AddRange(new CodeResolvePrimaryKeyStatements(tableSchema, transactionExpression, parameterPair.Value as UniqueConstraintParameterItem, targetDataSet)); } } // At this point, all the external variables have been resolved and the primary index of the target row has been // calculated in the parameter matrix. This will perform the destroy with the internal method. this.Statements.Add( new CodeMethodInvokeExpression(targetDataSet, String.Format("Destroy{0}", tableSchema.Name), destroyParameterMatrix.DestroyParameters)); }
/// <summary> /// Generates a property that gets the lock for the data model. /// </summary> public CurrentTransactionProperty(DataModelSchema dataModelSchema) { // /// <summary> // /// Gets the current DataModelTransaction. // /// </summary> // internal DataModelTransaction CurrentTransaction // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement("Gets the current DataModelTransaction.", true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.AddRange(new CodeCustomAttributesForProperties()); this.Attributes = MemberAttributes.Assembly | MemberAttributes.Final; this.Type = new CodeTypeReference(String.Format("{0}Transaction", dataModelSchema.Name)); this.Name = "CurrentTransaction"; // get // { // try // { CodeTryCatchFinallyStatement tryLockStatement = new CodeTryCatchFinallyStatement(); // global::System.Transactions.Transaction transaction = global::System.Transactions.Transaction.Current; // string localIdentifier = transaction.TransactionInformation.LocalIdentifier; tryLockStatement.TryStatements.Add( new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(Transaction)), "transaction", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Transaction)), "Current"))); tryLockStatement.TryStatements.Add( new CodeVariableDeclarationStatement( new CodeGlobalTypeReference(typeof(String)), "localIdentifier", new CodePropertyReferenceExpression( new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("transaction"), "TransactionInformation"), "LocalIdentifier"))); // global::System.Threading.Monitor.Enter(this.syncRoot); tryLockStatement.TryStatements.Add( new CodeMethodInvokeExpression(new CodeGlobalTypeReferenceExpression(typeof(Monitor)), "Enter", new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "syncRoot"))); // DataModelTransaction dataModelTransaction; CodeVariableReferenceExpression dataModelTransaction = new CodeRandomVariableReferenceExpression(); tryLockStatement.TryStatements.Add( new CodeVariableDeclarationStatement(new CodeTypeReference(String.Format("{0}Transaction", dataModelSchema.Name)), dataModelTransaction.VariableName)); // if ((this.transactionTable.TryGetValue(localIdentifier, out dataModelTransaction) == false)) // { CodeConditionStatement ifTransactionFound = new CodeConditionStatement( new CodeBinaryOperatorExpression( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "transactionTable"), "TryGetValue", new CodeVariableReferenceExpression("localIdentifier"), new CodeDirectionExpression(FieldDirection.Out, dataModelTransaction)), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(false))); // dataModelTransaction = new DataModelTransaction(transaction, this); ifTransactionFound.TrueStatements.Add( new CodeAssignStatement( dataModelTransaction, new CodeObjectCreateExpression( new CodeTypeReference(String.Format("{0}Transaction", dataModelSchema.Name)), new CodeVariableReferenceExpression("transaction"), new CodeThisReferenceExpression()))); // this.transactionTable.Add(localIdentifier, dataModelTransaction); ifTransactionFound.TrueStatements.Add( new CodeMethodInvokeExpression( new CodeVariableReferenceExpression("transactionTable"), "Add", new CodeVariableReferenceExpression("localIdentifier"), dataModelTransaction)); // transaction.TransactionCompleted += new global::System.Transactions.TransactionCompletedEventHandler(this.OnTransactionCompleted); ifTransactionFound.TrueStatements.Add( new CodeAttachEventStatement( new CodeEventReferenceExpression(new CodeVariableReferenceExpression("transaction"), "TransactionCompleted"), new CodeObjectCreateExpression( new CodeGlobalTypeReference(typeof(TransactionCompletedEventHandler)), new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), "OnTransactionCompleted")))); // } // return dataModelTransaction; tryLockStatement.TryStatements.Add(ifTransactionFound); tryLockStatement.TryStatements.Add(new CodeMethodReturnStatement(dataModelTransaction)); // } // finally // { // global::System.Threading.Monitor.Exit(this.syncRoot); // } tryLockStatement.FinallyStatements.Add( new CodeMethodInvokeExpression( new CodeGlobalTypeReferenceExpression(typeof(Monitor)), "Exit", new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "syncRoot"))); // } // } this.GetStatements.Add(tryLockStatement); // } }
/// <summary> /// Creates the CodeDOM for a method to insert a record into a table using transacted logic. /// </summary> /// <param name="tableSchema">A description of the table.</param> public CreateMethod(TableSchema tableSchema) { // Create a matrix of parameters for this operation. CreateParameterMatrix createParameterMatrix = new CreateParameterMatrix(tableSchema); // /// <summary> // /// Creates a Employee record. // /// </summary> // /// <param name="age">The required value for the Age column.</param> // /// <param name="departmentId">The required value for the DepartmentId column.</param> // /// <param name="employeeId">The required value for the EmployeeId column.</param> // /// <param name="raceCode">The optional value for the RaceCode column.</param> // [global::System.ServiceModel.OperationBehaviorAttribute(TransactionScopeRequired=true)] // [FluidTrade.Core.ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, ClaimType=FluidTrade.Core.ClaimTypes.Create, Resource=FluidTrade.Core.Resources.Application)] // public void CreateEmployee(int age, int departmentId, int employeeId, object raceCode) { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Creates a {0} record.", tableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { this.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">{1}</param>", parameterPair.Value.Name, parameterPair.Value.Description), true)); } this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(System.ServiceModel.OperationBehaviorAttribute)), new CodeAttributeArgument("TransactionScopeRequired", new CodePrimitiveExpression(true)))); //AR FB 408 - Remove Claims requirement //this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(ClaimsPrincipalPermission)), new CodeAttributeArgument(new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Security.Permissions.SecurityAction)), "Demand")), // new CodeAttributeArgument("ClaimType", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(ClaimTypes)), "Create")), // new CodeAttributeArgument("Resource", new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(Resources)), "Application")))); this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Name = string.Format("Create{0}", tableSchema.Name); foreach (KeyValuePair <string, ExternalParameterItem> parameterPair in createParameterMatrix.ExternalParameterItems) { this.Parameters.Add(parameterPair.Value.CodeParameterDeclarationExpression); } // // This provides a context for the middle tier transactions. // global::FluidTrade.Core.MiddleTierContext middleTierTransaction = global::FluidTrade.Core.MiddleTierContext.Current; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeCreateMiddleTierContextStatement(tableSchema.DataModel, transactionExpression)); // // Apply the defaults to optional parameters. // if ((raceCode == null)) { // raceCode = System.DBNull.Value; // } foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (columnSchema.IsNullable || columnSchema.DefaultValue != DBNull.Value) { CodeConditionStatement ifIsNull = new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null))); ifIsNull.TrueStatements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), CodeConvert.CreateConstantExpression(columnSchema.DefaultValue))); this.Statements.Add(ifIsNull); } } // // Find the parent Department record if it is required for a foreign key constraint. // FluidTrade.UnitTest.Server.DataModel.DepartmentRow departmentRowByFK_Department_Employee = FluidTrade.UnitTest.Server.DataModel.Department.FindByDepartmentId(new object[] { // departmentId}); // if ((departmentRowByFK_Department_Employee == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId)); // } // // This record locked for reading for the duration of the transaction. // departmentRowByFK_Department_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(departmentRowByFK_Department_Employee); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((departmentRowByFK_Department_Employee.RowState == System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId)); // } // // Find the parent Object record if it is required for a foreign key constraint. // FluidTrade.UnitTest.Server.DataModel.ObjectRow objectRowByFK_Object_Employee = FluidTrade.UnitTest.Server.DataModel.Object.FindByObjectId(new object[] { // employeeId}); // if ((objectRowByFK_Object_Employee == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", employeeId)); // } // // This record locked for reading for the duration of the transaction. // objectRowByFK_Object_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(objectRowByFK_Object_Employee); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((objectRowByFK_Object_Employee.RowState == System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", employeeId)); // } // // Find the parent Race record if it is required for a foreign key constraint. // if ((raceCode != System.DBNull.Value)) { // FluidTrade.UnitTest.Server.DataModel.RaceRow raceRowByFK_Race_Employee = FluidTrade.UnitTest.Server.DataModel.Race.FindByRaceCode(new object[] { // raceCode}); // if ((raceRowByFK_Race_Employee == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Race record ({0}) that doesn\'t exist", raceCode)); // } // // This record locked for reading for the duration of the transaction. // raceRowByFK_Race_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(raceRowByFK_Race_Employee); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((raceRowByFK_Race_Employee.RowState == System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Race record ({0}) that doesn\'t exist", raceCode)); // } // } foreach (KeyValuePair <string, RelationSchema> relationPair in tableSchema.ParentRelations) { if (tableSchema != relationPair.Value.ParentTable) { // This is the table containing the parent record that is to be locked for the transaction. TableSchema parentTable = relationPair.Value.ParentTable; // The varible name for the parent row is decorated with the foreign key name thus making it unique. CodeVariableReferenceExpression parentRowVariableExpression = new CodeRandomVariableReferenceExpression(); CodeTypeReference parentRowType = new CodeTypeReference(string.Format("{0}Row", parentTable.Name)); // This chains all the non-null values of the primary key into an expression that tests if the given key values // to the parent table have been provided in the input arguments to this method. If the provided values are // null, and the columns allow nulls, then there is no need to find the parent record. CodeExpression lockConditions = null; foreach (ColumnSchema columnSchema in relationPair.Value.ChildColumns) { if (columnSchema.IsNullable) { lockConditions = lockConditions == null ? new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.DBNull)), "Value")) : new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BitwiseAnd, lockConditions); } } // The statements to lock the row are added conditionally when the column is nullable. They are added to the // main part of the method when the constraint is required to match up with a parent record. CodeStatementCollection codeStatementCollection; if (lockConditions == null) { codeStatementCollection = this.Statements; } else { CodeConditionStatement ifParentKeyExists = new CodeConditionStatement(lockConditions); this.Statements.Add(ifParentKeyExists); codeStatementCollection = ifParentKeyExists.TrueStatements; } // FluidTrade.UnitTest.Server.DataModel.DepartmentRow departmentRowByFK_Department_Employee = FluidTrade.UnitTest.Server.DataModel.Department.FindByDepartmentId(new object[] { // departmentId}); // if ((departmentRowByFK_Department_Employee == null)) // { // throw new FluidTrade.Core.RecordNotFoundException("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId); // } CodeVariableReferenceExpression parentKeyExpression = new CodeRandomVariableReferenceExpression(); codeStatementCollection.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Object[])), parentKeyExpression.VariableName, new CodeKeyCreateExpression(relationPair.Value.ChildColumns))); if (tableSchema.PrimaryKey == null) { codeStatementCollection.Add(new CodeVariableDeclarationStatement(parentRowType, parentRowVariableExpression.VariableName, new CodeFindByRowExpression(parentTable, parentKeyExpression))); } else { codeStatementCollection.Add(new CodeVariableDeclarationStatement(parentRowType, parentRowVariableExpression.VariableName, new CodeFindByIndexExpression(parentTable, parentKeyExpression))); } codeStatementCollection.Add(new CodeCheckRecordExistsStatement(parentTable, parentRowVariableExpression, parentKeyExpression)); // // This record locked for reading for the duration of the transaction. // departmentRowByFK_Department_Employee.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(departmentRowByFK_Department_Employee); codeStatementCollection.Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, parentRowVariableExpression, parentTable.DataModel)); codeStatementCollection.Add(new CodeAddLockToTransactionExpression(transactionExpression, parentRowVariableExpression)); // // This makes sure the record wasn't deleted in the time between when it was found and the time it was locked. // if ((departmentRowByFK_Department_Employee.RowState == System.Data.DataRowState.Detached)) // { // throw new FluidTrade.Core.RecordNotFoundException("Attempt to access a Department record ({0}) that doesn\'t exist", departmentId); // } codeStatementCollection.Add(new CodeCheckRecordDetachedStatement(parentTable, parentRowVariableExpression, parentKeyExpression)); } } // // Create the Employee record. // FluidTrade.UnitTest.Server.DataModel.EmployeeRow employeeRow; // try { // FluidTrade.UnitTest.Server.DataModel.ReaderWriterLock.EnterWriteLock(); // employeeRow = ((FluidTrade.UnitTest.Server.DataModel.EmployeeRow)(FluidTrade.UnitTest.Server.DataModel.Employee.NewRow())); // } // finally { // FluidTrade.UnitTest.Server.DataModel.ReaderWriterLock.ExitWriteLock(); // } CodeVariableReferenceExpression rowVariableExpression = new CodeRandomVariableReferenceExpression(); this.Statements.Add(new CodeVariableDeclarationStatement(string.Format("{0}Row", tableSchema.Name), rowVariableExpression.VariableName)); CodeTryCatchFinallyStatement tryCreateRecord = new CodeTryCatchFinallyStatement(); tryCreateRecord.TryStatements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "EnterWriteLock")); tryCreateRecord.TryStatements.Add(new CodeAssignStatement(rowVariableExpression, new CodeCastExpression(new CodeTypeReference(string.Format("{0}Row", tableSchema.Name)), new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "NewRow")))); tryCreateRecord.FinallyStatements.Add( new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "ExitWriteLock")); this.Statements.Add(tryCreateRecord); // // This record is locked for writing for the duration of the transaction. // employeeRow.AcquireWriterLock(middleTierTransaction.AdoResourceManager.Guid, FluidTrade.UnitTest.Server.DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(employeeRow); this.Statements.Add(new CodeAcquireRecordWriterLockExpression(transactionExpression, rowVariableExpression, tableSchema)); this.Statements.Add(new CodeAddLockToTransactionExpression(transactionExpression, rowVariableExpression)); // // Create the Employee record in the ADO data model. // middleTierTransaction.AdoResourceManager.AddRecord(employeeRow); this.Statements.Add(new CodeAddRecordToTransactionExpression(transactionExpression, rowVariableExpression)); // try { // // Lock the owner table and any parent tables while the record is populated. Note that table locks are always held // // momentarily. // FluidTrade.UnitTest.Server.DataModel.ReaderWriterLock.EnterReadLock(); // employeeRow.BeginEdit(); // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.AgeColumn] = age; // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.DepartmentIdColumn] = departmentId; // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.EmployeeIdColumn] = employeeId; // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.RaceCodeColumn] = raceCode; // employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.RowVersionColumn] = System.Threading.Interlocked.Increment(ref FluidTrade.UnitTest.Server.DataModel.masterRowVersion); // FluidTrade.UnitTest.Server.DataModel.Employee.Rows.Add(employeeRow); // } // finally { // // The record create is finished and the momentary table locks are no longer needed. // employeeRow.EndEdit(); // FluidTrade.UnitTest.Server.DataModel.ReaderWriterLock.ExitWriteLock(); // } CodeTryCatchFinallyStatement tryFinallyStatement = new CodeTryCatchFinallyStatement(); tryFinallyStatement.TryStatements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "EnterWriteLock")); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(rowVariableExpression, "BeginEdit")); foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (!columnSchema.IsAutoIncrement) { CodeExpression sourceExpression; if (columnSchema.IsRowVersion) { sourceExpression = new CodeMethodInvokeExpression( new CodeFieldReferenceExpression( new CodeTypeReferenceExpression(tableSchema.DataModel.Name), String.Format("{0}DataSet", CommonConversion.ToCamelCase(tableSchema.DataModel.Name))), "IncrementRowVersion"); } else { sourceExpression = new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)); } tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), string.Format("{0}Column", columnSchema.Name))), sourceExpression)); } } tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "Rows"), "Add", rowVariableExpression)); tryFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(rowVariableExpression, "EndEdit")); tryFinallyStatement.FinallyStatements.Add( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "DataLock"), "ExitWriteLock")); this.Statements.Add(tryFinallyStatement); // // Add the Employee record to the SQL data model. // System.Data.SqlClient.SqlCommand sqlCommand = new global::System.Data.SqlClient.SqlCommand("insert \"Employee\" (\"Age\",\"DepartmentId\",\"EmployeeId\",\"RaceCode\",\"RowVersion\",\"Row" + // "Version\") values (@age,@departmentId,@employeeId,@raceCode,@rowVersion,@rowVersi" + // "on)", middleTierTransaction.SqlConnection); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@age", System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, false, 0, 0, null, System.Data.DataRowVersion.Current, age)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@departmentId", System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, false, 0, 0, null, System.Data.DataRowVersion.Current, departmentId)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@employeeId", System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, false, 0, 0, null, System.Data.DataRowVersion.Current, employeeId)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@raceCode", System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, false, 0, 0, null, System.Data.DataRowVersion.Current, raceCode)); // sqlCommand.Parameters.Add(new global::System.Data.SqlClient.SqlParameter("@rowVersion", System.Data.SqlDbType.BigInt, 0, System.Data.ParameterDirection.Input, false, 0, 0, null, System.Data.DataRowVersion.Current, employeeRow[FluidTrade.UnitTest.Server.DataModel.Employee.RowVersionColumn])); // sqlCommand.ExecuteNonQuery(); if (tableSchema.IsPersistent) { CodeVariableReferenceExpression sqlCommandExpression = new CodeRandomVariableReferenceExpression(); string columnList = string.Empty; string variableList = string.Empty; int columnIndex = 0; foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (columnSchema.IsPersistent) { columnList += string.Format(columnIndex < tableSchema.Columns.Count - 1 ? "\"{0}\"," : "\"{0}\"", columnSchema.Name); variableList += string.Format(columnIndex < tableSchema.Columns.Count - 1 ? "@{0}," : "@{0}", CommonConversion.ToCamelCase(columnSchema.Name)); columnIndex++; } } string insertCommandText = string.Format("insert \"{0}\" ({1}) values ({2})", tableSchema.Name, columnList, variableList); this.Statements.Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlCommand)), sqlCommandExpression.VariableName, new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlCommand)), new CodePrimitiveExpression(insertCommandText), new CodePropertyReferenceExpression(transactionExpression, "SqlConnection")))); foreach (ColumnSchema columnSchema in tableSchema.Columns.Values) { if (columnSchema.IsPersistent) { string variableName = CommonConversion.ToCamelCase(columnSchema.Name); if (columnSchema.IsAutoIncrement) { CodeExpression codeExpression = new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), string.Format("{0}Column", columnSchema.Name))); this.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(sqlCommandExpression, "Parameters"), "Add", new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlParameter)), new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.ParameterDirection)), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowVersion)), "Current"), codeExpression))); } else { CodeExpression sourceExpression = columnSchema.IsRowVersion ? (CodeExpression) new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "RowVersionColumn")) : (CodeExpression) new CodeArgumentReferenceExpression(variableName); this.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(sqlCommandExpression, "Parameters"), "Add", new CodeObjectCreateExpression(new CodeGlobalTypeReference(typeof(System.Data.SqlClient.SqlParameter)), new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.ParameterDirection)), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowVersion)), "Current"), sourceExpression))); } } } this.Statements.Add(new CodeMethodInvokeExpression(sqlCommandExpression, "ExecuteNonQuery")); } // DataModel.DestinationOrder.OnRowValidate(new DestinationOrderRowChangeEventArgs(pe9564f2717374e96a76d5222e2258784, System.Data.DataRowAction.Add)); this.Statements.Add( new CodeMethodInvokeExpression( new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), "OnRowValidate", new CodeObjectCreateExpression( string.Format("{0}RowChangeEventArgs", tableSchema.Name), rowVariableExpression, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.Data.DataRowAction)), "Add")))); // Cast the Auto-Increment values back to their native types when returning from this method. foreach (KeyValuePair <string, ColumnSchema> columnPair in tableSchema.Columns) { ColumnSchema columnSchema = columnPair.Value; if (columnSchema.IsAutoIncrement) { this.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression(CommonConversion.ToCamelCase(columnSchema.Name)), new CodeCastExpression(new CodeGlobalTypeReference(columnSchema.DataType), new CodeIndexerExpression(rowVariableExpression, new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), tableSchema.Name), string.Format("{0}Column", columnSchema.Name)))))); } } // } }
/// <summary> /// Creates a property that gets the parent row. /// </summary> /// <param name="relationSchema">The foreign key that references the parent table.</param> public ParentRowProperty(RelationSchema relationSchema) { // These constructs are used several times to generate the property. TableSchema childTable = relationSchema.ChildTable; TableSchema parentTable = relationSchema.ParentTable; string rowTypeName = String.Format("{0}Row", parentTable.Name); string tableFieldName = String.Format("table{0}", childTable.Name); string relationName = relationSchema.IsDistinctPathToParent ? String.Format("{0}{1}Relation", parentTable.Name, childTable.Name) : String.Format("{0}{1}By{2}Relation", relationSchema.ParentTable.Name, relationSchema.ChildTable.Name, relationSchema.Name); string relationFieldName = relationSchema.IsDistinctPathToParent ? String.Format("{0}{1}Relation", relationSchema.ParentTable.Name, relationSchema.ChildTable.Name) : String.Format("{0}{1}By{2}Relation", relationSchema.ParentTable.Name, relationSchema.ChildTable.Name, relationSchema.Name); // /// <summary> // /// Gets the parent row in the Currency table. // /// </summary> // public CurrencyRow CurrencyRow // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Gets the parent row in the {0} table.", relationSchema.ParentTable.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeGlobalTypeReference(typeof(DebuggerNonUserCodeAttribute)))); this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Type = new CodeTypeReference(rowTypeName); this.Name = relationSchema.IsDistinctPathToParent ? rowTypeName : String.Format("{0}By{1}", rowTypeName, relationSchema.Name); // get // { // DataModelTransaction k7494 = DataModel.CurrentTransaction; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("{0}Transaction", parentTable.DataModel.Name)), transactionExpression.VariableName, new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(parentTable.DataModel.Name), "CurrentTransaction"))); // if ((this.IsLockHeld(k7494.TransactionId) == false)) // { // throw new global::System.ServiceModel.FaultException<Teraque.SynchronizationLockFault>(new global::Teraque.SynchronizationLockFault("AccountBase")); // } this.GetStatements.AddRange( new CodeCheckReaderLockHeldStatements(new CodeThisReferenceExpression(), relationSchema.ChildTable, transactionExpression)); // try // { // ((TenantDataModel)this.Table.DataSet).dataLock.EnterReadLock(); // return ((CurrencyRow)(this.GetParentRow(this.tableAccountBase.CurrencyAccountBaseRelation))); CodeTryCatchFinallyStatement tryCatchFinallyStatement = new CodeTryCatchFinallyStatement(); tryCatchFinallyStatement.TryStatements.Add( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression( new CodeCastExpression( new CodeTypeReference(String.Format("Tenant{0}", parentTable.DataModelSchema.Name)), new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Table"), "DataSet")), "dataLock"), "EnterReadLock")); tryCatchFinallyStatement.TryStatements.Add( new CodeMethodReturnStatement( new CodeCastExpression( rowTypeName, new CodeMethodInvokeExpression( new CodeThisReferenceExpression(), "GetParentRow", new CodePropertyReferenceExpression( new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), tableFieldName), relationFieldName))))); // } // finally // { // ((TenantDataModel)this.Table.DataSet).dataLock.ExitReadLock(); // } tryCatchFinallyStatement.FinallyStatements.Add( new CodeMethodInvokeExpression( new CodeFieldReferenceExpression( new CodeCastExpression( new CodeTypeReference(String.Format("Tenant{0}", parentTable.DataModelSchema.Name)), new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Table"), "DataSet")), "dataLock"), "ExitReadLock")); this.GetStatements.Add(tryCatchFinallyStatement); // } // } }
/// <summary> /// Creates a property that gets or sets the value of an item in a row. /// </summary> /// <param name="tableSchema">The table to which this row belongs.</param> /// <param name="columnSchema">The nullable column.</param> public ColumnProperty(TableSchema tableSchema, ColumnSchema columnSchema) { // /// <summary> // /// Gets or sets the data in the AccountId column. // /// </summary> // public global::System.Guid AccountId // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(String.Format("Gets or sets the data in the {0} column.", columnSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final; this.Type = new CodeGlobalTypeReference(columnSchema.DataType); this.Name = columnSchema.Name; // get // { // DataModelTransaction r1233 = DataModel.Current; CodeVariableReferenceExpression transactionExpression = new CodeRandomVariableReferenceExpression(); this.GetStatements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("{0}Transaction", tableSchema.DataModel.Name)), transactionExpression.VariableName, new CodePropertyReferenceExpression( new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "CurrentTransaction"))); // if ((this.IsLockHeld(dataModelTransaction.transactionId) == false)) // { // throw new global::System.ServiceModel.FaultException<SynchronizationLockFault>(new global::Teraque.SynchronizationLockFault("Account")); // } this.GetStatements.AddRange( new CodeCheckReaderLockHeldStatements(new CodeThisReferenceExpression(), tableSchema, transactionExpression)); // return ((global::System.Guid)(this[this.tableAccount.AccountIdColumn])); // } CodeMethodReturnStatement returnStatement = new CodeMethodReturnStatement( new CodeCastExpression( this.Type, new CodeArrayIndexerExpression( new CodeThisReferenceExpression(), new CodePropertyReferenceExpression( new CodePropertyReferenceExpression( new CodeThisReferenceExpression(), String.Format("table{0}", tableSchema.Name)), String.Format("{0}Column", columnSchema.Name))))); if (columnSchema.IsNullable) { CodeTryCatchFinallyStatement tryCatchBlock = new CodeTryCatchFinallyStatement(); tryCatchBlock.TryStatements.Add(returnStatement); CodeCatchClause catchStrongTypeException = new CodeCatchClause("e", new CodeGlobalTypeReference(typeof(InvalidCastException))); catchStrongTypeException.Statements.Add( new CodeThrowExceptionStatement( new CodeObjectCreateExpression( new CodeGlobalTypeReference(typeof(StrongTypingException)), new CodePrimitiveExpression("Cannot get value because it is DBNull."), new CodeArgumentReferenceExpression("e")))); tryCatchBlock.CatchClauses.Add(catchStrongTypeException); this.GetStatements.Add(tryCatchBlock); } else { this.GetStatements.Add(returnStatement); } // set // { // DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction; this.SetStatements.Add( new CodeVariableDeclarationStatement( new CodeTypeReference(String.Format("{0}Transaction", tableSchema.DataModel.Name)), transactionExpression.VariableName, new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModel.Name), "CurrentTransaction"))); // if ((this.IsWriterLockHeld(dataModelTransaction.transactionId) == false)) // { // throw new global::System.ServiceModel.FaultException<SynchronizationLockFault>(new global::Teraque.SynchronizationLockFault("Account")); // } this.SetStatements.AddRange(new CodeCheckWriterLockHeldStatements(new CodeThisReferenceExpression(), tableSchema, transactionExpression)); // this[this.tableAccount.AccountIdColumn] = value; // } this.SetStatements.Add(new CodeAssignStatement(new CodeArrayIndexerExpression(new CodeThisReferenceExpression(), new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), String.Format("table{0}", tableSchema.Name)), String.Format("{0}Column", columnSchema.Name))), new CodePropertySetValueReferenceExpression())); // } }
/// <summary> /// Recurse into a hierarchy of relations until a table is found that can resolve external identifiers. /// </summary> /// <param name="foreignKeyConstraintParameterItem">The original foreign key parameter to be resolved.</param> /// <param name="foreignKeyConstraintSchema">The current level of the table hierarchy.</param> /// <returns>An expression representing the unique row identified by the foreign key.</returns> public void RecurseIntoRelation(CodeVariableReferenceExpression rowExpression, ForeignKeyConstraintSchema rootForeignKeyConstraintSchema, CodeExpression rootKeyExpression, ForeignKeyConstraintSchema currentForeignKeyConstraintSchema) { // Each time through the recursion, the parent table will be examined to see if there is another ancestor which can be // used to resolve the external interfaces. If one is found, the recursion continues into the ancestor, if not, we've // found the ancestor that can resolve the external identifiers. TableSchema parentTableSchema = currentForeignKeyConstraintSchema.RelatedTable; ForeignKeyConstraintSchema parentForeignKeyConstraintSchema = parentTableSchema.ParentConstraint; // If this is the end of the line for the foreign relations that can be use to uniquely identify the original row, then // stop recursing and attempt to find a unique constraint. The recursion then unwinds and the row at the original // level of the recursion has values that can be used to identify the target record. if (parentForeignKeyConstraintSchema == null) { // object[] configurationKey0 = new object[] { // configurationId, // "FK_Object_Employee"}; // ConfigurationRow configurationRow0 = DataModel.Configuration.ConfigurationKey.Find(configurationKey0); // if ((configurationRow0 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey0)); // } // configurationRow0.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(configurationRow0); // if ((configurationRow0.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey0)); // } CodeVariableReferenceExpression configurationKeyExpression = new CodeRandomVariableReferenceExpression(); Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Object[])), configurationKeyExpression.VariableName, new CodeKeyCreateExpression(new CodeArgumentReferenceExpression("configurationId"), new CodePrimitiveExpression(rootForeignKeyConstraintSchema.Name)))); CodeVariableReferenceExpression configurationRowExpression = new CodeRandomVariableReferenceExpression(); Add(new CodeVariableDeclarationStatement(new CodeTypeReference("ConfigurationRow"), configurationRowExpression.VariableName, new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(parentTableSchema.DataModel.Name), "Configuration"), "ConfigurationKey"), "Find", configurationKeyExpression))); TableSchema configurationTableSchema = parentTableSchema.DataModel.Tables["Configuration"]; Add(new CodeCheckRecordExistsStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); Add(new CodeAcquireRecordReaderLockExpression(transactionExpression, configurationRowExpression, parentTableSchema.DataModel)); Add(new CodeAddLockToTransactionExpression(transactionExpression, configurationRowExpression)); Add(new CodeCheckRecordDetachedStatement(configurationTableSchema, configurationRowExpression, configurationKeyExpression)); // IObjectIndex dataIndex0 = ((IObjectIndex)(DataModel.Object.Indices[configurationRow0.IndexName])); // ObjectRow objectRow1 = dataIndex0.Find(engineerId); // if ((objectRow1 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", engineerId)); // } CodeTypeReference indexType = new CodeTypeReference(string.Format("I{0}Index", parentTableSchema.Name)); CodeVariableReferenceExpression indexExpression = new CodeRandomVariableReferenceExpression(); CodeExpression indexNameExpression = new CodePropertyReferenceExpression(configurationRowExpression, "IndexName"); Add(new CodeVariableDeclarationStatement(indexType, indexExpression.VariableName, new CodeCastExpression(indexType, new CodeIndexerExpression(new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(parentTableSchema.DataModel.Name), parentTableSchema.Name), "Indices"), indexNameExpression)))); Add(new CodeCheckIndexExistsStatement(indexExpression, parentTableSchema, indexNameExpression)); CodeTypeReference rowTypeReference = new CodeTypeReference(string.Format("{0}Row", parentTableSchema.Name)); Add(new CodeVariableDeclarationStatement(rowTypeReference, rowExpression.VariableName, new CodeMethodInvokeExpression(indexExpression, "Find", rootKeyExpression))); Add(new CodeCheckRecordExistsStatement(parentTableSchema, rowExpression, rootKeyExpression)); // objectRow1.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(objectRow1); // if ((objectRow1.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", engineerId)); // } Add(new CodeAcquireRecordReaderLockExpression(this.transactionExpression, rowExpression, parentTableSchema.DataModel)); Add(new CodeAddLockToTransactionExpression(this.transactionExpression, rowExpression)); Add(new CodeCheckRecordDetachedStatement(parentTableSchema, rowExpression, rootKeyExpression)); } else { // This will recurse into the hierarchy and emit code that will find and lock each row in the line of ancestors to // the current table. When there are no more ancestors to be found, code will be generated to select a record // based on a unique constraint. The generated code then unwinds the relationship choosing one distinct descendant // after another until all the foreign relationships to the starting table have been resolved. CodeVariableReferenceExpression parentRow = new CodeRandomVariableReferenceExpression(); RecurseIntoRelation(parentRow, rootForeignKeyConstraintSchema, rootKeyExpression, parentForeignKeyConstraintSchema); // // Employee level of the engineerId foreign key search. // object[] employeeKey1 = new object[] { // objectRow1.ObjectId}; // EmployeeRow employeeRow2 = DataModel.Employee.EmployeeKey.Find(employeeKey1); // if ((employeeRow2 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeKey1)); // } CodeVariableReferenceExpression keyExpression = new CodeRandomVariableReferenceExpression(); Add(new CodeVariableDeclarationStatement(new CodeGlobalTypeReference(typeof(System.Object[])), keyExpression.VariableName, new CodeKeyCreateExpression(parentRow, parentForeignKeyConstraintSchema.RelatedColumns))); CodeTypeReference rowType = new CodeTypeReference(string.Format("{0}Row", parentTableSchema.Name)); UniqueConstraintSchema uniqueConstraintSchema = parentTableSchema.GetUniqueConstraint(parentForeignKeyConstraintSchema.Columns); Add(new CodeVariableDeclarationStatement(rowType, rowExpression.VariableName, new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(parentTableSchema.DataModel.Name), parentTableSchema.Name), uniqueConstraintSchema.Name), "Find", keyExpression))); Add(new CodeCheckRecordExistsStatement(parentTableSchema, rowExpression, keyExpression)); // employeeRow2.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(employeeRow2); // if ((employeeRow2.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeKey1)); // } Add(new CodeAcquireRecordReaderLockExpression(this.transactionExpression, rowExpression, parentTableSchema.DataModel)); Add(new CodeAddLockToTransactionExpression(this.transactionExpression, rowExpression)); Add(new CodeCheckRecordDetachedStatement(parentTableSchema, rowExpression, keyExpression)); } }
/// <summary> /// Resolves the variables related to foreign tables. /// </summary> /// <param name="tableSchema">A description of a table.</param> /// <param name="transactionExpression">Used to support locking and provide database resources.</param> /// <param name="foreignKeyConstraintParameterItem">A description of a variable related to a foreign table.</param> public CodeResolveExternalVariableStatements(TableSchema tableSchema, CodeVariableReferenceExpression transactionExpression, ForeignKeyConstraintParameterItem foreignKeyConstraintParameterItem) { // This is the foreign key that will be resolved here. ForeignKeyConstraintSchema foreignKeyConstraintSchema = foreignKeyConstraintParameterItem.ForeignKeyConstraintSchema; // // This will resolve the optional managerKey foreign key. // object managerId; foreach (ForeignKeyVariableItem foreignKeyVariableItem in foreignKeyConstraintParameterItem.ForeignKeyVariables) { this.Add(new CodeVariableDeclarationStatement(foreignKeyVariableItem.DataType, foreignKeyVariableItem.Expression.VariableName)); } // Optional parameters tied to foreign constraints can be explicitly set to DBNull.Value by passing an empty key. They // can implicitly be set to the default by passing null. CodeStatementCollection codeStatementCollection = this; if (foreignKeyConstraintParameterItem.IsNullable) { // if ((managerKey == null)) { // managerId = null; // } CodeConditionStatement ifIsNull = new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(foreignKeyConstraintParameterItem.Name), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null))); codeStatementCollection = ifIsNull.FalseStatements; foreach (ForeignKeyVariableItem foreignKeyVariableItem in foreignKeyConstraintParameterItem.ForeignKeyVariables) { ifIsNull.TrueStatements.Add(new CodeAssignStatement(foreignKeyVariableItem.Expression, new CodePrimitiveExpression(null))); } // else { // if ((managerKey.Length == 0)) { // managerId = global::System.DBNull.Value; // } CodeConditionStatement ifArrayEmpty = new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression(foreignKeyConstraintParameterItem.Name), "Length"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(0))); foreach (ForeignKeyVariableItem foreignKeyVariableItem in foreignKeyConstraintParameterItem.ForeignKeyVariables) { ifArrayEmpty.TrueStatements.Add(new CodeAssignStatement(foreignKeyVariableItem.Expression, new CodePropertyReferenceExpression(new CodeGlobalTypeReferenceExpression(typeof(System.DBNull)), "Value"))); } codeStatementCollection = ifArrayEmpty.FalseStatements; ifIsNull.FalseStatements.Add(ifArrayEmpty); // else { this.Add(ifIsNull); } // object[] configurationKey2 = new object[] { // configurationId, // "FK_Manager_Engineer"}; // ConfigurationRow configurationRow3 = DataModel.Configuration.ConfigurationKey.Find(configurationKey2); // if ((configurationRow3 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey2)); // } // configurationRow3.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(configurationRow3); // if ((configurationRow3.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Configuration record ({0}) that doesn\'t exist", configurationKey2)); // } // IObjectIndex dataIndex1 = ((IObjectIndex)(DataModel.Object.Indices[configurationRow3.IndexName])); // ObjectRow objectRow4 = dataIndex1.Find(managerKey); // if ((objectRow4 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", managerKey)); // } // objectRow4.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(objectRow4); // if ((objectRow4.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Object record ({0}) that doesn\'t exist", managerKey)); // } // // Employee level of the managerKey foreign key search. // object[] employeeKey3 = new object[] { // objectRow4.ObjectId}; // EmployeeRow employeeRow5 = DataModel.Employee.EmployeeKey.Find(employeeKey3); // if ((employeeRow5 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeKey3)); // } // employeeRow5.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(employeeRow5); // if ((employeeRow5.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Employee record ({0}) that doesn\'t exist", employeeKey3)); // } // // Manager level of the managerKey foreign key search. // object[] managerKey4 = new object[] { // employeeRow5.EmployeeId}; // ManagerRow managerRow6 = DataModel.Manager.ManagerKey.Find(managerKey4); // if ((managerRow6 == null)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Manager record ({0}) that doesn\'t exist", managerKey4)); // } // managerRow6.AcquireReaderLock(middleTierTransaction.AdoResourceManager.Guid, DataModel.lockTimeout); // middleTierTransaction.AdoResourceManager.AddLock(managerRow6); // if ((managerRow6.RowState == global::System.Data.DataRowState.Detached)) { // throw new global::System.ServiceModel.FaultException<RecordNotFoundFault>(new global::FluidTrade.Core.RecordNotFoundFault("Attempt to access a Manager record ({0}) that doesn\'t exist", managerKey4)); // } CodeVariableReferenceExpression rootRowExpression = new CodeRandomVariableReferenceExpression(); CodeArgumentReferenceExpression rootKeyExpression = new CodeArgumentReferenceExpression(foreignKeyConstraintParameterItem.Name); codeStatementCollection.AddRange(new CodeResolveForeignKeyExpression(rootRowExpression, transactionExpression, rootKeyExpression, foreignKeyConstraintSchema)); // managerId = managerRow6.ManagerId; // } for (int columnIndex = 0; columnIndex < foreignKeyConstraintSchema.Columns.Length; columnIndex++) { if (foreignKeyConstraintParameterItem.ForeignKeyVariables[columnIndex] != null) { codeStatementCollection.Add(new CodeAssignStatement(foreignKeyConstraintParameterItem.ForeignKeyVariables[columnIndex].Expression, new CodePropertyReferenceExpression(rootRowExpression, foreignKeyConstraintSchema.RelatedColumns[columnIndex].Name))); } } // } }