private void DeleteChildren(TableSchema parentTable, CodeStatementCollection codeStatements) { // // Delete each of the child Department records in a cascade. // ServerDataModel.DepartmentRow[] departmentRows = objectRow.GetDepartmentRows(); // for (int departmentIndex = 0; departmentIndex < departmentRows.Length; departmentIndex = (departmentIndex + 1)) // { // // Get the next department in the list. // ServerDataModel.DepartmentRow departmentRow = departmentRows[departmentIndex]; // // Lock the ADO record. // departmentRow.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(departmentRow.ReaderWriterLock); // // Optimistic Concurrency Check. // if ((departmentRow.RowVersion != rowVersion)) // { // throw new System.Exception("This record is busy. Please try again later."); // } // // Delete the SQL record as part of a transaction. // SqlCommand departmentCommand = new SqlCommand(@"delete ""Department"" where ""DepartmentId""=@departmentId", sqlResourceManager.SqlConnection); // departmentCommand.Parameters.Add(new SqlParameter("@departmentId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, departmentRow[ServerDataModel.Department.DepartmentIdColumn])); // sqlCommands.Add(departmentCommand); // // Delete the ADO record as part of a transaction. // adoResourceManager.Add(departmentRow); // departmentRow[ServerDataModel.Department.RowVersionColumn] = ServerDataModel.IncrementRowVersion(); // departmentRow.Delete(); // } foreach (KeyrefSchema childKeyref in parentTable.ChildKeyrefs) { TableSchema childTable = childKeyref.Selector; if (childTable.RootTable == parentTable && childTable != this.TableSchema) { continue; } string parentRowVariable = string.Format("{0}Row", Generate.CamelCase(parentTable.Name)); string rowArrayType = string.Format("{0}.{1}Row[]", this.ServerSchema.Name, childTable.Name); string rowArrayVariable = string.Format("{0}{1}Rows", Generate.CamelCase(parentTable.Name), childTable.Name); string rowType = string.Format("{0}.{1}Row", this.ServerSchema.Name, childTable.Name); string rowVariable = string.Format("{0}Row", Generate.CamelCase(childTable.Name)); string methodName = string.Format("Get{0}Rows", childTable.Name); string iteratorVariable = string.Format("{0}Index", Generate.CamelCase(childTable.Name)); codeStatements.Add(new CodeCommentStatement(string.Format("Delete each of the child {0} records in a cascade.", childTable.Name))); codeStatements.Add(new CodeVariableDeclarationStatement(rowArrayType, rowArrayVariable, new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(parentRowVariable), methodName))); CodeStatementCollection iteratorStatements = new CodeStatementCollection(); iteratorStatements.Add(new CodeCommentStatement(string.Format("Get the next {0} row in the list of children and lock it for the duration of the transaction.", childTable.Name))); iteratorStatements.Add(new CodeVariableDeclarationStatement(rowType, rowVariable, new CodeIndexerExpression(new CodeVariableReferenceExpression(rowArrayVariable), new CodeVariableReferenceExpression(iteratorVariable)))); iteratorStatements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "ReaderWriterLock"), "AcquireWriterLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")))); iteratorStatements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "ReaderWriterLock")))); // // The Optimistic Concurrency check allows only one client to update a record at a time. // if ((departmentRow.RowVersion != rowVersion)) // { // throw new System.Exception("This record is busy. Please try again later."); // } if (childTable == this.TableSchema) { iteratorStatements.Add(new CodeCommentStatement("The Optimistic Concurrency check allows only one client to update a record at a time.")); iteratorStatements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "RowVersion"), CodeBinaryOperatorType.IdentityInequality, new CodeArgumentReferenceExpression("rowVersion")), new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(System.Exception), new CodePrimitiveExpression("This record is busy. Please try again later."))))); } DeleteChildren(childTable, iteratorStatements); // // Delete the Department record from the SQL data model. // sqlCommand = new SqlCommand("delete \"Department\" where \"DepartmentId\"=@departmentId", sqlResourceManager.SqlConnection); // sqlCommand.Parameters.Add(new SqlParameter("@departmentId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, departmentRow[ServerDataModel.Department.DepartmentIdColumn])); // sqlCommands.Add(sqlCommand); if (childTable.IsPersistent) { iteratorStatements.Add(new CodeCommentStatement(string.Format("Delete the {0} record from the SQL data model.", childTable.Name))); string whereClause = string.Empty; foreach (ColumnSchema columnSchema in childTable.PrimaryKey.Fields) { whereClause += string.Format("\"{0}\"=@{1}", columnSchema.Name, Generate.CamelCase(columnSchema.Name)); } string deleteCommandText = string.Format("delete \"{0}\" where {1}", childTable.Name, whereClause); iteratorStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("sqlCommand"), new CodeObjectCreateExpression("SqlCommand", new CodePrimitiveExpression(deleteCommandText), new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("sqlResourceManager"), "SqlConnection")))); foreach (ColumnSchema columnSchema in childTable.PrimaryKey.Fields) { string variableName = Generate.CamelCase(columnSchema.Name); CodeExpression codeExpression = new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(childTable.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, childTable.Name)), string.Format("{0}Column", columnSchema.Name))); iteratorStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeExpression[] { new CodeObjectCreateExpression("SqlParameter", new CodeExpression[] { new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), codeExpression }) })); } iteratorStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("sqlCommand"), "ExecuteNonQuery")); } // // Delete the Department record from the ADO data model. // adoResourceManager.Add(departmentRow); // departmentRow[ServerDataModel.Department.RowVersionColumn] = ServerDataModel.IncrementRowVersion(); // departmentRow.Delete(); iteratorStatements.Add(new CodeCommentStatement(string.Format("Delete the {0} record from the ADO data model.", childTable.Name))); iteratorStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeVariableReferenceExpression(rowVariable))); CodeTryCatchFinallyStatement tryFinallyStatement = new CodeTryCatchFinallyStatement(); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowVariable), "BeginEdit")); tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(new CodeVariableReferenceExpression(rowVariable), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, childTable.Name)), "RowVersionColumn")), new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), "IncrementRowVersion"))); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowVariable), "Delete")); tryFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowVariable), "EndEdit")); iteratorStatements.Add(tryFinallyStatement); CodeStatement[] iteratorArray = new CodeStatement[iteratorStatements.Count]; iteratorStatements.CopyTo(iteratorArray, 0); codeStatements.Add(new CodeIterationStatement(new CodeVariableDeclarationStatement(typeof(System.Int32), iteratorVariable, new CodePrimitiveExpression(0)), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(iteratorVariable), CodeBinaryOperatorType.LessThan, new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowArrayVariable), "Length")), new CodeAssignStatement(new CodeVariableReferenceExpression(iteratorVariable), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(iteratorVariable), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))), iteratorArray)); } }
/// <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 Insert(TableSchema tableSchema) : base(tableSchema) { // /// <summary>Inserts a Department record.</summary> // /// <param name="departmentId">The value for the DepartmentId column.</param> // /// <param name="description">The value for the Description column.</param> // /// <param name="externalId0">The value for the ExternalId0 column.</param> // /// <param name="externalId1">The value for the ExternalId1 column.</param> // /// <param name="name">The value for the Name column.</param> // /// <param name="typeCode">The value for the TypeCode column.</param> // public static void Insert(out int departmentId, object description, object externalId0, object externalId1, string name, object typeCode, out long rowVersion) // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Inserts a {0} record.", this.TableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (!this.TableSchema.IsPrimaryKeyColumn(columnSchema) || columnSchema.DeclaringType == this.TableSchema.TypeSchema) { this.Comments.Add(new CodeCommentStatement(string.Format(@"<param name=""{0}"">The value for the {1} column.</param>", Generate.CamelCase(columnSchema.Name), columnSchema.Name), true)); } } this.Comments.Add(new CodeCommentStatement(@"<param name=""rowVersion"">Used for Optimistic Concurrency Checking.</param>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; this.Name = "Insert"; foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (!this.TableSchema.IsPrimaryKeyColumn(columnSchema) || columnSchema.DeclaringType == this.TableSchema.TypeSchema) { Type typeColumn = columnSchema.DataType; Type typeVariable = columnSchema.MinOccurs == 0 || columnSchema.DefaultValue != null ? typeof(object) : typeColumn; CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression(typeVariable, Generate.CamelCase(columnSchema.Name)); if (this.TableSchema.IsAutogeneratedColumn(columnSchema)) { parameter.Direction = FieldDirection.Out; } this.Parameters.Add(parameter); } } CodeParameterDeclarationExpression rowVersionParameter = new CodeParameterDeclarationExpression(typeof(long), "rowVersion"); rowVersionParameter.Direction = FieldDirection.Out; this.Parameters.Add(rowVersionParameter); // // This method is part of a larger transaction. Instead of passing the transaction and the resource managers down // // through several layers of methods, they are acccessed as ambient properties of the Transaction class. // Transaction transaction = Transaction.Current; // AdoResourceManager adoResourceManager = ((AdoResourceManager)(transaction["ADO Data Model"])); // SqlResourceManager sqlResourceManager = ((SqlResourceManager)(transaction["SQL Data Model"])); this.Statements.Add(new CodeCommentStatement("This method is part of a larger transaction. Instead of passing the transaction and the resource managers down")); this.Statements.Add(new CodeCommentStatement("through several layers of methods, they are acccessed as ambient properties of the Transaction class.")); this.Statements.Add(new CodeVariableDeclarationStatement("Transaction", "transaction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("Transaction"), "Current"))); this.Statements.Add(new CodeVariableDeclarationStatement("AdoResourceManager", "adoResourceManager", new CodeCastExpression("AdoResourceManager", new CodeIndexerExpression(new CodeVariableReferenceExpression("transaction"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.TableSchema.Name), "VolatileResource"))))); this.Statements.Add(new CodeVariableDeclarationStatement("SqlResourceManager", "sqlResourceManager", new CodeCastExpression("SqlResourceManager", new CodeIndexerExpression(new CodeVariableReferenceExpression("transaction"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.TableSchema.Name), "DurableResource"))))); // // Lock the parent Race record for the duration of the transaction. // if (raceCode != null) // { // ServerDataModel.RaceRow raceRow = ServerDataModel.Race.FindByRaceCode(((int)raceCode)); // raceRow.ReaderWriterLock.AcquireReaderLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(raceRow.ReaderWriterLock); // } foreach (KeyrefSchema parentKey in this.TableSchema.ParentKeyrefs) { if (!this.TableSchema.IsBaseKeyref(parentKey)) { TableSchema parentTable = parentKey.Refer.Selector; this.Statements.Add(new CodeCommentStatement(string.Format("Lock the parent {0} record for the duration of the transaction.", parentTable.Name))); CodeExpression lockConditions = null; foreach (ColumnSchema columnSchema in parentKey.Fields) { if (columnSchema.MinOccurs == 0) { lockConditions = lockConditions == null ? new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(Generate.CamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)) : new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(Generate.CamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BitwiseAnd, lockConditions); } } List <CodeStatement> lockParentRow = new List <CodeStatement>(); string parentRowName = string.Format("{0}Row", Generate.CamelCase(parentTable.Name)); string methodName = "FindBy"; List <CodeExpression> keyList = new List <CodeExpression>(); for (int fieldIndex = 0; fieldIndex < parentKey.Fields.Length; fieldIndex++) { ColumnSchema parentColumn = parentKey.Refer.Fields[fieldIndex]; ColumnSchema childColumn = parentKey.Fields[fieldIndex]; methodName += parentColumn.Name; keyList.Add(childColumn.MinOccurs == 0 ? (CodeExpression) new CodeCastExpression(childColumn.DataType, new CodeArgumentReferenceExpression(Generate.CamelCase(childColumn.Name))) : (CodeExpression) new CodeArgumentReferenceExpression(Generate.CamelCase(childColumn.Name))); } lockParentRow.Add(new CodeVariableDeclarationStatement(new CodeTypeReference(string.Format("{0}.{1}Row", this.ServerSchema.Name, parentTable.Name)), parentRowName, new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, parentTable.Name)), methodName, keyList.ToArray()))); lockParentRow.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(parentRowName), "ReaderWriterLock"), "AcquireReaderLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")))); lockParentRow.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(parentRowName), "ReaderWriterLock")))); if (lockConditions == null) { this.Statements.AddRange(lockParentRow.ToArray()); } else { this.Statements.Add(new CodeConditionStatement(lockConditions, lockParentRow.ToArray())); } } } // // Apply Fixed Values // int objectTypeCode = 12; bool isFixedCommentEmitted = false; foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (columnSchema.FixedValue != null) { if (!isFixedCommentEmitted) { this.Statements.Add(new CodeCommentStatement("Apply Fixed Values")); isFixedCommentEmitted = true; } Type typeVariable = columnSchema.MinOccurs == 0 ? typeof(object) : columnSchema.DataType; this.Statements.Add(new CodeVariableDeclarationStatement(typeVariable, Generate.CamelCase(columnSchema.Name), Generate.PrimativeExpression(columnSchema.FixedValue))); } } // // Apply Defaults // if ((description == null)) // { // description = System.DBNull.Value; // } // if ((externalId0 == null)) // { // externalId0 = System.DBNull.Value; // } // if ((externalId1 == null)) // { // externalId1 = System.DBNull.Value; // } // if ((typeCode == null)) // { // typeCode = "Department"; // } bool isDefaultCommentEmitted = false; foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (columnSchema.DefaultValue != null) { if (!isDefaultCommentEmitted) { this.Statements.Add(new CodeCommentStatement("Apply Defaults")); isDefaultCommentEmitted = true; } Type typeVariable = columnSchema.MinOccurs == 0 ? typeof(object) : columnSchema.DataType; this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)), new CodeStatement[] { new CodeAssignStatement(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)), Generate.PrimativeExpression(columnSchema.DefaultValue)) })); } } bool isCommandDeclared = false; foreach (TableSchema familyTable in this.TableSchema.TableHierarchy) { // To reduce the frequency of deadlocking, the tables are always locked in alphabetical order. This section collects // all the table locks that are used for this operation and organizes them in a list that is used to generate the // locking and releasing statements below. List <TableSchema> parentList = new List <TableSchema>(); foreach (KeyrefSchema parentKeyref in familyTable.ParentKeyrefs) { parentList.Add(parentKeyref.Refer.Selector); } parentList.Sort(); // // Add the Object record to the ADO data model. // ServerDataModel.ObjectRow objectRow = ServerDataModel.Object.NewObjectRow(); // objectRow.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(objectRow.ReaderWriterLock); // adoResourceManager.Add(objectRow); // try // { // ServerDataModel.Object.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite); // ServerDataModel.Object.ReaderWriterLock.AcquireReaderLock(System.Threading.Timeout.Infinite); // objectRow[ServerDataModel.Object.DescriptionColumn] = description; // objectRow[ServerDataModel.Object.ExternalId0Column] = externalId0; // objectRow[ServerDataModel.Object.ExternalId1Column] = externalId1; // objectRow[ServerDataModel.Object.NameColumn] = name; // objectRow[ServerDataModel.Object.TypeCodeColumn] = typeCode; // objectRow[ServerDataModel.Object.RowVersionColumn] = ServerDataModel.IncrementRowVersion(); // } // finally // { // ServerDataModel.Object.ReaderWriterLock.ReleaseWriterLock(); // ServerDataModel.Object.ReaderWriterLock.ReleaseReaderLock(); // } string rowName = string.Format("{0}Row", Generate.CamelCase(familyTable.Name)); this.Statements.Add(new CodeCommentStatement(string.Format("Add the {0} record to the ADO data model.", familyTable.Name))); this.Statements.Add(new CodeVariableDeclarationStatement(string.Format("{0}.{1}Row", this.ServerSchema.Name, familyTable.Name), rowName, new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), familyTable.Name), string.Format("New{0}Row", familyTable.Name)))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowName), "ReaderWriterLock"), "AcquireWriterLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite"))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowName), "ReaderWriterLock"))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeVariableReferenceExpression(rowName))); CodeTryCatchFinallyStatement tryFinallyStatement = new CodeTryCatchFinallyStatement(); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowName), "BeginEdit")); foreach (ColumnSchema columnSchema in familyTable.Columns) { if (columnSchema.DeclaringType == familyTable.TypeSchema) { if (columnSchema.IsAutoIncrement) { continue; } if (familyTable.IsInheritedKey(columnSchema)) { TableSchema baseTable = familyTable.BaseTable; int keyIndex = Array.IndexOf(familyTable.PrimaryKey.Fields, columnSchema); tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(new CodeVariableReferenceExpression(rowName), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), string.Format("{0}Column", columnSchema.Name))), new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(baseTable.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, baseTable.Name)), string.Format("{0}Column", baseTable.PrimaryKey.Fields[keyIndex].Name))) )); } else { tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(new CodeVariableReferenceExpression(rowName), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), string.Format("{0}Column", columnSchema.Name))), new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)))); } } } tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(new CodeVariableReferenceExpression(rowName), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), "RowVersionColumn")), new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), "IncrementRowVersion"))); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), string.Format("Add{0}Row", familyTable.Name), new CodeVariableReferenceExpression(rowName))); tryFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowName), "EndEdit")); this.Statements.Add(tryFinallyStatement); // // Add the Object record to the SQL data model. // System.Data.SqlClient.SqlCommand sqlCommand = new SqlCommand("insert \"Object\" (\"Description\",\"ExternalId0\",\"ExternalId1\",\"Name\",\"ObjectId\",\"Typ" + // "eCode\",\"RowVersion\") values (@description,@externalId0,@externalId1,@name,@objec" + // "tId,@typeCode,@rowVersion)", sqlResourceManager.SqlConnection); // sqlCommand.Parameters.Add(new SqlParameter("@description", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, description)); // sqlCommand.Parameters.Add(new SqlParameter("@externalId0", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, externalId0)); // sqlCommand.Parameters.Add(new SqlParameter("@externalId1", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, externalId1)); // sqlCommand.Parameters.Add(new SqlParameter("@name", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, name)); // sqlCommand.Parameters.Add(new SqlParameter("@objectId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, objectRow[ServerDataModel.Object.ObjectIdColumn])); // sqlCommand.Parameters.Add(new SqlParameter("@typeCode", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, typeCode)); // sqlCommand.Parameters.Add(new SqlParameter("@rowVersion", SqlDbType.BigInt, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, objectRow[ServerDataModel.Object.RowVersionColumn])); // sqlCommand.ExecuteNonQuery(); if (this.TableSchema.IsPersistent) { this.Statements.Add(new CodeCommentStatement(string.Format("Add the {0} record to the SQL data model.", familyTable.Name))); string columnList = string.Empty; string variableList = string.Empty; foreach (ColumnSchema columnSchema in familyTable.Columns) { if (columnSchema.IsPersistent && columnSchema.DeclaringType == familyTable.TypeSchema) { columnList += string.Format("\"{0}\",", columnSchema.Name); variableList += string.Format("@{0},", Generate.CamelCase(columnSchema.Name)); } } columnList += "\"RowVersion\""; variableList += "@rowVersion"; string insertCommandText = string.Format("insert \"{0}\" ({1}) values ({2})", familyTable.Name, columnList, variableList); if (isCommandDeclared) { this.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("sqlCommand"), new CodeObjectCreateExpression("SqlCommand", new CodePrimitiveExpression(insertCommandText), new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("sqlResourceManager"), "SqlConnection")))); } else { isCommandDeclared = true; this.Statements.Add(new CodeVariableDeclarationStatement(typeof(System.Data.SqlClient.SqlCommand), "sqlCommand", new CodeObjectCreateExpression("SqlCommand", new CodePrimitiveExpression(insertCommandText), new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("sqlResourceManager"), "SqlConnection")))); } foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (columnSchema.IsPersistent && columnSchema.DeclaringType == familyTable.TypeSchema) { string variableName = Generate.CamelCase(columnSchema.Name); if (familyTable.IsAutogeneratedColumn(columnSchema)) { CodeExpression codeExpression = new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(familyTable.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), string.Format("{0}Column", columnSchema.Name))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeExpression[] { new CodeObjectCreateExpression("SqlParameter", new CodeExpression[] { new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), codeExpression }) })); } else { this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeExpression[] { new CodeObjectCreateExpression("SqlParameter", new CodeExpression[] { new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), new CodeArgumentReferenceExpression(variableName) }) })); } } } this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeObjectCreateExpression("SqlParameter", new CodePrimitiveExpression("@rowVersion"), new CodeTypeReferenceExpression("SqlDbType.BigInt"), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(familyTable.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), "RowVersionColumn"))))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("sqlCommand"), "ExecuteNonQuery")); } } // // Autogenerated values are returned to the caller. // departmentId = (int)departmentRow[ServerDataModel.Department.DepartmentIdColumn]; // rowVersion = (long)departmentRow[ServerDataModel.Department.RowVersionColumn]; this.Statements.Add(new CodeCommentStatement("Autogenerated values are returned to the caller.")); foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (this.TableSchema.IsAutogeneratedColumn(columnSchema) && columnSchema.DeclaringType == this.TableSchema.TypeSchema) { this.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)), new CodeCastExpression(columnSchema.DataType, new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(this.TableSchema.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, this.TableSchema.Name)), string.Format("{0}Column", columnSchema.Name)))))); } } this.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression("rowVersion"), new CodeCastExpression(typeof(long), new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(this.TableSchema.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, this.TableSchema.Name)), "RowVersionColumn"))))); }
/// <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 Delete(TableSchema tableSchema) : base(tableSchema) { // To reduce the frequency of deadlocking, the tables are always locked in alphabetical order. This section collects // all the table locks that are used for this operation and organizes them in a list that is used to generate the // locking and releasing statements below. List <LockRequest> tableLockList = new List <LockRequest>(); foreach (TableSchema familyTable in this.TableSchema.TableHierarchy) { tableLockList.Add(new WriteRequest(familyTable)); } foreach (TableSchema childTable in this.TableSchema.Descendants) { tableLockList.Add(new WriteRequest(childTable)); } tableLockList.Sort(); // Shorthand notations for the elements used to construct the interface to this table: string tableTypeName = string.Format("{0}.{1}DataTable", this.ServerSchema.Name, this.TableSchema.Name); string tableVariableName = string.Format("{0}Table", this.TableSchema.Name[0].ToString().ToLower() + this.TableSchema.Name.Remove(0, 1)); string rowTypeName = string.Format("{0}.{1}Row", this.ServerSchema.Name, this.TableSchema.Name); string rowVariableName = string.Format("{0}Row", this.TableSchema.Name[0].ToString().ToLower() + this.TableSchema.Name.Remove(0, 1)); string identityColumnName = this.TableSchema.PrimaryKey.Fields[0].Name; string identityVariableName = identityColumnName[0].ToString().ToLower() + identityColumnName.Remove(0, 1); // /// <summary>Deletes a Employee record.</summary> // /// <param name="employeeId">The value for the EmployeeId column.</param> // /// <param name="rowVersion">Used for Optimistic Concurrency Checking.</param> // public static void Delete(int employeeId, ref long rowVersion) // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Deletes a {0} record.", this.TableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (this.TableSchema.IsPrimaryKeyColumn(columnSchema) && columnSchema.DeclaringType == this.TableSchema.TypeSchema) { this.Comments.Add(new CodeCommentStatement(string.Format(@"<param name=""{0}"">The value for the {1} column.</param>", Generate.CamelCase(columnSchema.Name), columnSchema.Name), true)); } } this.Comments.Add(new CodeCommentStatement(@"<param name=""rowVersion"">Used for Optimistic Concurrency Checking.</param>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; this.Name = "Delete"; foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (this.TableSchema.IsPrimaryKeyColumn(columnSchema) && columnSchema.DeclaringType == this.TableSchema.TypeSchema) { Type typeColumn = columnSchema.DataType; Type parameterType = this.TableSchema.IsPrimaryKeyColumn(columnSchema) ? typeColumn : typeof(object); CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression(parameterType, Generate.CamelCase(columnSchema.Name)); this.Parameters.Add(parameter); } } CodeParameterDeclarationExpression rowVersionParameter = new CodeParameterDeclarationExpression(typeof(long), "rowVersion"); this.Parameters.Add(rowVersionParameter); // // This method is part of a larger transaction. Instead of passing the transaction and the resource managers down // // through several layers of methods, they are acccessed as ambient properties of the Transaction class. // Transaction transaction = Transaction.Current; // AdoResourceManager adoResourceManager = ((AdoResourceManager)(transaction["ADO Data Model"])); // SqlResourceManager sqlResourceManager = ((SqlResourceManager)(transaction["SQL Data Model"])); this.Statements.Add(new CodeCommentStatement("This method is part of a larger transaction. Instead of passing the transaction and the resource managers down")); this.Statements.Add(new CodeCommentStatement("through several layers of methods, they are acccessed as ambient properties of the Transaction class.")); this.Statements.Add(new CodeVariableDeclarationStatement("Transaction", "transaction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("Transaction"), "Current"))); this.Statements.Add(new CodeVariableDeclarationStatement("AdoResourceManager", "adoResourceManager", new CodeCastExpression("AdoResourceManager", new CodeIndexerExpression(new CodeVariableReferenceExpression("transaction"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.TableSchema.Name), "VolatileResource"))))); this.Statements.Add(new CodeVariableDeclarationStatement("SqlResourceManager", "sqlResourceManager", new CodeCastExpression("SqlResourceManager", new CodeIndexerExpression(new CodeVariableReferenceExpression("transaction"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.TableSchema.Name), "DurableResource"))))); // // This is used below to assemble the SQL commands. // SqlCommand sqlCommand = null; this.Statements.Add(new CodeCommentStatement("This is used below to assemble the SQL commands.")); this.Statements.Add(new CodeVariableDeclarationStatement("SqlCommand", "sqlCommand", new CodePrimitiveExpression(null))); // // The Department record is locked for the duration of the transaction. // ServerDataModel.DepartmentRow departmentRow = ((ServerDataModel.DepartmentRow)(ServerDataModel.Department.FindByDepartmentId(departmentId))); // if ((departmentRow == null)) // { // throw new System.Exception(string.Format("Attempt to update a Department record ({0}) that doesn\'t exist", departmentId)); // } // departmentRow.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite); TableSchema rootTable = this.TableSchema.RootTable; this.Statements.Add(new CodeCommentStatement(string.Format("The {0} record is deleted from the most distant descendant back up to the root object in order to preserved", rootTable.Name))); this.Statements.Add(new CodeCommentStatement("the integrity of the cascading relations.")); string rowVariable = string.Format("{0}Row", Generate.CamelCase(rootTable.Name)); string rowType = string.Format("{0}.{1}Row", this.ServerSchema.Name, rootTable.Name); string findMethodName = string.Format("FindBy"); string exceptionFormat = string.Empty; int parameterCounter = 0; List <CodeExpression> methodParameters = new List <CodeExpression>(); List <CodeExpression> exceptionParameters = new List <CodeExpression>(); foreach (ColumnSchema columnSchema in this.TableSchema.PrimaryKey.Fields) { methodParameters.Add(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name))); exceptionParameters.Add(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name))); exceptionFormat += string.Format("{{0}}", parameterCounter++); } foreach (ColumnSchema columnSchema in rootTable.PrimaryKey.Fields) { findMethodName += columnSchema.Name; } exceptionParameters.Insert(0, new CodePrimitiveExpression(string.Format("Attempt to delete a {0} record ({1}) that doesn't exist", rootTable.Name, exceptionFormat))); this.Statements.Add(new CodeVariableDeclarationStatement(string.Format("{0}.{1}Row", this.ServerSchema.Name, rootTable.Name), rowVariable, new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), rootTable.Name), findMethodName, methodParameters.ToArray()))); this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(rowVariable), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)), new CodeThrowExceptionStatement(new CodeObjectCreateExpression("MarkThree.RecordNotFoundException", exceptionParameters.ToArray())))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "ReaderWriterLock"), "AcquireWriterLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite"))); this.Statements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "ReaderWriterLock")))); DeleteChildren(rootTable, this.Statements); // // Delete the Department record from the SQL data model. // sqlCommand = new SqlCommand("delete \"Department\" where \"DepartmentId\"=@departmentId", sqlResourceManager.SqlConnection); // sqlCommand.Parameters.Add(new SqlParameter("@departmentId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, departmentRow[ServerDataModel.Department.DepartmentIdColumn])); // sqlCommands.Add(sqlCommand); if (this.TableSchema.IsPersistent) { this.Statements.Add(new CodeCommentStatement(string.Format("Delete the {0} record from the SQL data model.", rootTable.Name))); string whereClause = string.Empty; foreach (ColumnSchema columnSchema in rootTable.PrimaryKey.Fields) { whereClause += string.Format("\"{0}\"=@{1}", columnSchema.Name, Generate.CamelCase(columnSchema.Name)); } string deleteCommandText = string.Format("delete \"{0}\" where {1}", rootTable.Name, whereClause); this.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("sqlCommand"), new CodeObjectCreateExpression("SqlCommand", new CodePrimitiveExpression(deleteCommandText), new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("sqlResourceManager"), "SqlConnection")))); foreach (ColumnSchema columnSchema in rootTable.PrimaryKey.Fields) { string variableName = Generate.CamelCase(columnSchema.Name); CodeExpression codeExpression = new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(rootTable.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, rootTable.Name)), string.Format("{0}Column", columnSchema.Name))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeExpression[] { new CodeObjectCreateExpression("SqlParameter", new CodeExpression[] { new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), codeExpression }) })); } this.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("sqlCommand"), "ExecuteNonQuery")); } // // Delete the Department record from the ADO data model. // adoResourceManager.Add(departmentRow); // departmentRow[ServerDataModel.Department.RowVersionColumn] = ServerDataModel.IncrementRowVersion(); // departmentRow.Delete(); this.Statements.Add(new CodeCommentStatement(string.Format("Delete the {0} record from the ADO data model.", rootTable.Name))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeVariableReferenceExpression(rowVariable))); CodeTryCatchFinallyStatement tryFinallyStatement = new CodeTryCatchFinallyStatement(); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowVariable), "BeginEdit")); tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(new CodeVariableReferenceExpression(rowVariable), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, rootTable.Name)), "RowVersionColumn")), new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), "IncrementRowVersion"))); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowVariable), "Delete")); tryFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowVariable), "EndEdit")); this.Statements.Add(tryFinallyStatement); }
/// <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 Update(TableSchema tableSchema) : base(tableSchema) { // To reduce the frequency of deadlocking, the tables are always locked in alphabetical order. This section collects // all the table locks that are used for this operation and organizes them in a list that is used to generate the // locking and releasing statements below. List <LockRequest> tableLockList = new List <LockRequest>(); foreach (TableSchema familyTable in this.TableSchema.TableHierarchy) { tableLockList.Add(new WriteRequest(familyTable)); } foreach (KeyrefSchema parentKeyref in this.TableSchema.ParentKeyrefs) { if (!this.TableSchema.IsBaseKeyref(parentKeyref)) { tableLockList.Add(new ReadRequest(parentKeyref.Refer.Selector)); } } tableLockList.Sort(); // /// <summary>Updates a Employee record.</summary> // /// <param name="age">The value for the Age column.</param> // /// <param name="departmentId">The value for the DepartmentId column.</param> // /// <param name="description">The value for the Description column.</param> // /// <param name="employeeId">The value for the EmployeeId column.</param> // /// <param name="externalId0">The value for the ExternalId0 column.</param> // /// <param name="externalId1">The value for the ExternalId1 column.</param> // /// <param name="name">The value for the Name column.</param> // /// <param name="raceCode">The value for the RaceCode column.</param> // /// <param name="typeCode">The value for the TypeCode column.</param> // public static void Update(object age, object departmentId, object description, int employeeId, object externalId0, object externalId1, object name, object raceCode, object typeCode, ref long rowVersion) // { this.Comments.Add(new CodeCommentStatement("<summary>", true)); this.Comments.Add(new CodeCommentStatement(string.Format("Updates a {0} record.", this.TableSchema.Name), true)); this.Comments.Add(new CodeCommentStatement("</summary>", true)); foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (!this.TableSchema.IsPrimaryKeyColumn(columnSchema) || columnSchema.DeclaringType == this.TableSchema.TypeSchema) { this.Comments.Add(new CodeCommentStatement(string.Format(@"<param name=""{0}"">The value for the {1} column.</param>", Generate.CamelCase(columnSchema.Name), columnSchema.Name), true)); } } this.Comments.Add(new CodeCommentStatement(@"<param name=""rowVersion"">Used for Optimistic Concurrency Checking.</param>", true)); this.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static; this.Name = "Update"; foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (!this.TableSchema.IsPrimaryKeyColumn(columnSchema) || columnSchema.DeclaringType == this.TableSchema.TypeSchema) { Type typeColumn = columnSchema.DataType; Type parameterType = this.TableSchema.IsPrimaryKeyColumn(columnSchema) ? typeColumn : typeof(object); CodeParameterDeclarationExpression parameter = new CodeParameterDeclarationExpression(parameterType, Generate.CamelCase(columnSchema.Name)); this.Parameters.Add(parameter); } } CodeParameterDeclarationExpression rowVersionParameter = new CodeParameterDeclarationExpression(typeof(long), "rowVersion"); rowVersionParameter.Direction = FieldDirection.Ref; this.Parameters.Add(rowVersionParameter); // // This method is part of a larger transaction. Instead of passing the transaction and the resource managers down // // through several layers of methods, they are acccessed as ambient properties of the Transaction class. // Transaction transaction = Transaction.Current; // AdoResourceManager adoResourceManager = ((AdoResourceManager)(transaction["ADO Data Model"])); // SqlResourceManager sqlResourceManager = ((SqlResourceManager)(transaction["SQL Data Model"])); this.Statements.Add(new CodeCommentStatement("This method is part of a larger transaction. Instead of passing the transaction and the resource managers down")); this.Statements.Add(new CodeCommentStatement("through several layers of methods, they are acccessed as ambient properties of the Transaction class.")); this.Statements.Add(new CodeVariableDeclarationStatement("Transaction", "transaction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("Transaction"), "Current"))); this.Statements.Add(new CodeVariableDeclarationStatement("AdoResourceManager", "adoResourceManager", new CodeCastExpression("AdoResourceManager", new CodeIndexerExpression(new CodeVariableReferenceExpression("transaction"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.TableSchema.Name), "VolatileResource"))))); this.Statements.Add(new CodeVariableDeclarationStatement("SqlResourceManager", "sqlResourceManager", new CodeCastExpression("SqlResourceManager", new CodeIndexerExpression(new CodeVariableReferenceExpression("transaction"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.TableSchema.Name), "DurableResource"))))); // // The Department record is locked for the duration of the transaction. // ServerDataModel.DepartmentRow departmentRow = ((ServerDataModel.DepartmentRow)(ServerDataModel.Department.FindByDepartmentId(departmentId))); // if ((departmentRow == null)) // { // throw new System.Exception(string.Format("Attempt to update a Department record ({0}) that doesn\'t exist", departmentId)); // } // departmentRow.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(departmentRow.ReaderWriterLock); this.Statements.Add(new CodeCommentStatement(string.Format("The {0} record is locked for the duration of the transaction.", this.TableSchema.Name))); string rowVariable = string.Format("{0}Row", Generate.CamelCase(this.TableSchema.Name)); string rowType = string.Format("{0}.{1}Row", this.ServerSchema.Name, this.TableSchema.Name); string findMethodName = string.Format("FindBy"); string exceptionFormat = string.Empty; int parameterCounter = 0; List <CodeExpression> methodParameters = new List <CodeExpression>(); List <CodeExpression> exceptionParameters = new List <CodeExpression>(); foreach (ColumnSchema columnSchema in this.TableSchema.PrimaryKey.Fields) { findMethodName += columnSchema.Name; methodParameters.Add(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name))); exceptionParameters.Add(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name))); exceptionFormat += string.Format("{{0}}", parameterCounter++); } exceptionParameters.Insert(0, new CodePrimitiveExpression(string.Format("Attempt to update a {0} record ({1}) that doesn't exist", this.TableSchema.Name, exceptionFormat))); this.Statements.Add(new CodeVariableDeclarationStatement(string.Format("{0}.{1}Row", this.ServerSchema.Name, this.TableSchema.Name), rowVariable, new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), this.TableSchema.Name), findMethodName, methodParameters.ToArray()))); this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(rowVariable), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)), new CodeThrowExceptionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(Exception)), new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(string)), "Format", exceptionParameters.ToArray()))))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "ReaderWriterLock"), "AcquireWriterLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite"))); this.Statements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "ReaderWriterLock")))); // // The Optimistic Concurrency check allows only one client to update a record at a time. // if ((departmentRow.RowVersion != rowVersion)) // { // throw new System.Exception("This record is busy. Please try again later."); // } this.Statements.Add(new CodeCommentStatement("The Optimistic Concurrency check allows only one client to update a record at a time.")); this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(rowVariable), "RowVersion"), CodeBinaryOperatorType.IdentityInequality, new CodeArgumentReferenceExpression("rowVersion")), new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(System.Exception), new CodePrimitiveExpression("This record is busy. Please try again later."))))); // // The base Department record is locked for the duration of the transaction. // ServerDataModel.ObjectRow objectRow = departmentRow.ObjectRow; // objectRow.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite); TableSchema baseTable0 = this.TableSchema.BaseTable; CodeExpression baseRowAccessor = new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(this.TableSchema.Name))); while (baseTable0 != null) { this.Statements.Add(new CodeCommentStatement(string.Format("The base {0} record is locked for the duration of the transaction.", this.TableSchema.Name))); string baseRowVariable = string.Format("{0}Row", Generate.CamelCase(baseTable0.Name)); baseRowAccessor = new CodeFieldReferenceExpression(baseRowAccessor, string.Format("{0}Row", baseTable0.Name)); this.Statements.Add(new CodeVariableDeclarationStatement(string.Format("{0}.{1}Row", this.ServerSchema.Name, baseTable0.Name), baseRowVariable, baseRowAccessor)); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(baseRowVariable), "ReaderWriterLock"), "AcquireWriterLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite"))); this.Statements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(baseRowVariable), "ReaderWriterLock")))); baseTable0 = baseTable0.BaseTable; } // // Lock the current parent Department record for the duration of the transaction. // ServerDataModel.DepartmentRow currentDepartmentRow = employeeRow.DepartmentRow; // currentDepartmentRow.ReaderWriterLock.AcquireReaderLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(currentDepartmentRow); // // Lock the current parent Race record for the duration of the transaction. // if ((employeeRow.RaceRow != null)) // { // ServerDataModel.RaceRow currentRaceRow = employeeRow.RaceRow; // currentRaceRow.ReaderWriterLock.AcquireReaderLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(currentRaceRow); // } foreach (TableSchema familyTable in this.TableSchema.TableHierarchy) { foreach (KeyrefSchema parentKeyref in familyTable.ParentKeyrefs) { if (!familyTable.IsBaseKeyref(parentKeyref)) { this.Statements.Add(new CodeCommentStatement(string.Format("Lock the current parent {0} record for the duration of the transaction.", parentKeyref.Refer.Selector.Name))); string parentRowType = string.Format("{0}.{1}Row", this.ServerSchema.Name, parentKeyref.Refer.Selector.Name); string parentRowVariable = string.Format("current{0}Row", parentKeyref.Refer.Selector.Name); string parentAccessor = familyTable.ParentKeyrefCount(parentKeyref.Refer.Selector) == 1 ? string.Format("{0}Row", parentKeyref.Refer.Selector.Name) : string.Format("{0}RowBy{1}", parentKeyref.Refer.Selector.Name, parentKeyref.Name); List <CodeStatement> parentRowLock = new List <CodeStatement>(); parentRowLock.Add(new CodeVariableDeclarationStatement(parentRowType, parentRowVariable, new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(familyTable.Name))), parentAccessor))); parentRowLock.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(parentRowVariable), "ReaderWriterLock"), "AcquireReaderLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")))); parentRowLock.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(parentRowVariable), "ReaderWriterLock")))); if (parentKeyref.IsNullable) { this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(familyTable.Name))), parentAccessor), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), parentRowLock.ToArray())); } else { this.Statements.AddRange(parentRowLock.ToArray()); } } } } // // This will provide the defaults elements of the Object table that haven't changed. // if ((description == null)) // { // description = objectRow[ServerDataModel.Object.DescriptionColumn]; // } // if ((externalId0 == null)) // { // externalId0 = objectRow[ServerDataModel.Object.ExternalId0Column]; // } // if ((externalId1 == null)) // { // externalId1 = objectRow[ServerDataModel.Object.ExternalId1Column]; // } // if ((name == null)) // { // name = objectRow[ServerDataModel.Object.NameColumn]; // } // if ((typeCode == null)) // { // typeCode = objectRow[ServerDataModel.Object.TypeCodeColumn]; // } foreach (TableSchema familyTable in this.TableSchema.TableHierarchy) { bool isDefaultCommentEmitted = false; foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (!familyTable.IsPrimaryKeyColumn(columnSchema) && columnSchema.DeclaringType == familyTable.TypeSchema) { if (!isDefaultCommentEmitted) { this.Statements.Add(new CodeCommentStatement(string.Format("This will provide the defaults elements of the {0} table that haven't changed.", familyTable.Name))); isDefaultCommentEmitted = true; } Type typeVariable = columnSchema.MinOccurs == 0 ? typeof(object) : columnSchema.DataType; this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(null)), new CodeAssignStatement(new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)), new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(familyTable.Name))), new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), familyTable.Name), string.Format("{0}Column", columnSchema.Name)))))); } } } // // Lock the proposed parent Department record for the duration of the transaction. // ServerDataModel.DepartmentRow proposedDepartmentRow = ServerDataModel.Department.FindByDepartmentId(((int)(departmentId))); // proposedDepartmentRow.ReaderWriterLock.AcquireReaderLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(proposedDepartmentRow); // // Lock the proposed parent Race record for the duration of the transaction. // if ((raceCode != null)) // { // ServerDataModel.RaceRow proposedRaceRow = ServerDataModel.Race.FindByRaceCode(((int)(raceCode))); // proposedRaceRow.ReaderWriterLock.AcquireReaderLock(System.Threading.Timeout.Infinite); // adoResourceManager.Add(proposedRaceRow); // } foreach (TableSchema familyTable in this.TableSchema.TableHierarchy) { foreach (KeyrefSchema parentKeyref in familyTable.ParentKeyrefs) { if (!familyTable.IsBaseKeyref(parentKeyref)) { this.Statements.Add(new CodeCommentStatement(string.Format("Lock the proposed parent {0} record for the duration of the transaction.", parentKeyref.Refer.Selector.Name))); List <CodeStatement> parentRowLock = new List <CodeStatement>(); string parentRowVariable = string.Format("proposed{0}Row", parentKeyref.Refer.Selector.Name); string parentRowType = string.Format("{0}.{1}Row", this.ServerSchema.Name, parentKeyref.Refer.Selector.Name); string findByMethod0 = string.Format("FindBy"); List <CodeExpression> methodParameters0 = new List <CodeExpression>(); foreach (ColumnSchema columnSchema in parentKeyref.Fields) { findByMethod0 += columnSchema.Name; methodParameters0.Add(new CodeCastExpression(columnSchema.DataType, new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)))); } parentRowLock.Add(new CodeVariableDeclarationStatement(parentRowType, parentRowVariable, new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), parentKeyref.Refer.Selector.Name), findByMethod0, methodParameters0.ToArray()))); parentRowLock.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(parentRowVariable), "ReaderWriterLock"), "AcquireReaderLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")))); parentRowLock.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(parentRowVariable), "ReaderWriterLock")))); CodeExpression lockProposedConditions = null; foreach (ColumnSchema columnSchema in parentKeyref.Fields) { if (columnSchema.MinOccurs == 0) { lockProposedConditions = lockProposedConditions == null ? new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(Generate.CamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(DBNull)), "Value")) : new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression(Generate.CamelCase(columnSchema.Name)), CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null)), CodeBinaryOperatorType.BitwiseAnd, lockProposedConditions); } } if (lockProposedConditions == null) { this.Statements.AddRange(parentRowLock.ToArray()); } else { this.Statements.Add(new CodeConditionStatement(lockProposedConditions, parentRowLock.ToArray())); } } } } // This will generate the ADO and SQL updates to the data model for each table in the class hierarchy. bool isCommandDeclared = false; foreach (TableSchema familyTable in this.TableSchema.TableHierarchy) { // To reduce the frequency of deadlocking, the tables are always locked in alphabetical order. This section collects // all the table locks that are used for this operation and organizes them in a list that is used to generate the // locking and releasing statements below. List <TableSchema> parentList = new List <TableSchema>(); foreach (KeyrefSchema parentKeyref in familyTable.ParentKeyrefs) { parentList.Add(parentKeyref.Refer.Selector); } parentList.Sort(); // // Update the Object record in the ADO data model. // adoResourceManager.Add(objectRow); // try // { // objectRow.BeginEdit(); // objectRow[ServerDataModel.Object.DescriptionColumn] = description; // objectRow[ServerDataModel.Object.ExternalId0Column] = externalId0; // objectRow[ServerDataModel.Object.ExternalId1Column] = externalId1; // objectRow[ServerDataModel.Object.NameColumn] = name; // objectRow[ServerDataModel.Object.TypeCodeColumn] = typeCode; // objectRow[ServerDataModel.Object.RowVersionColumn] = ServerDataModel.IncrementRowVersion(); // } // finally // { // objectRow.EndEdit(); // } this.Statements.Add(new CodeCommentStatement(string.Format("Update the {0} record in the ADO data model.", familyTable.Name))); string rowName = string.Format("{0}Row", Generate.CamelCase(familyTable.Name)); this.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("adoResourceManager"), "Add", new CodeVariableReferenceExpression(rowName))); CodeTryCatchFinallyStatement tryFinallyStatement = new CodeTryCatchFinallyStatement(); tryFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowName), "BeginEdit")); foreach (ColumnSchema columnSchema in familyTable.Columns) { if (columnSchema.DeclaringType == familyTable.TypeSchema) { if (columnSchema.IsAutoIncrement || familyTable.IsPrimaryKeyColumn(columnSchema)) { continue; } tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(new CodeVariableReferenceExpression(rowName), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), string.Format("{0}Column", columnSchema.Name))), new CodeArgumentReferenceExpression(Generate.CamelCase(columnSchema.Name)))); } } tryFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeIndexerExpression(new CodeVariableReferenceExpression(rowName), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), "RowVersionColumn")), new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(this.ServerSchema.Name), "IncrementRowVersion"))); tryFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(rowName), "EndEdit")); this.Statements.Add(tryFinallyStatement); // // Update the Object record in the SQL data model. // SqlCommand sqlCommand = new SqlCommand("update \"Object\" set \"Description\"=@description,\"ExternalId0\"=@externalId0,\"Extern" + // "alId1\"=@externalId1,\"Name\"=@name,\"TypeCode\"=@typeCode,\"RowVersion\"=@rowVersion w" + // "here \"ObjectId\"=@objectId", sqlResourceManager.SqlConnection); // sqlCommand.Parameters.Add(new SqlParameter("@description", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, description)); // sqlCommand.Parameters.Add(new SqlParameter("@externalId0", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, externalId0)); // sqlCommand.Parameters.Add(new SqlParameter("@externalId1", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, externalId1)); // sqlCommand.Parameters.Add(new SqlParameter("@name", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, name)); // sqlCommand.Parameters.Add(new SqlParameter("@objectId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, objectRow[ServerDataModel.Object.ObjectIdColumn])); // sqlCommand.Parameters.Add(new SqlParameter("@typeCode", SqlDbType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, typeCode)); // sqlCommand.Parameters.Add(new SqlParameter("@rowVersion", SqlDbType.BigInt, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, objectRow[ServerDataModel.Object.RowVersionColumn])); // sqlCommand.ExecuteNonQuery(); // sqlCommands.Add(sqlCommand); if (this.TableSchema.IsPersistent) { this.Statements.Add(new CodeCommentStatement(string.Format("Update the {0} record in the SQL data model.", familyTable.Name))); string setList = string.Empty; foreach (ColumnSchema columnSchema in familyTable.Columns) { if (columnSchema.IsPersistent && !familyTable.IsPrimaryKeyColumn(columnSchema) && columnSchema.DeclaringType == familyTable.TypeSchema) { setList += string.Format("\"{0}\"=@{1},", columnSchema.Name, Generate.CamelCase(columnSchema.Name)); } } setList += "\"RowVersion\"=@rowVersion"; string whereClause = string.Empty; foreach (ColumnSchema columnSchema in familyTable.PrimaryKey.Fields) { whereClause += string.Format("\"{0}\"=@{1}", columnSchema.Name, Generate.CamelCase(columnSchema.Name)); } string insertCommandText = string.Format("update \"{0}\" set {1} where {2}", familyTable.Name, setList, whereClause); if (isCommandDeclared) { this.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("sqlCommand"), new CodeObjectCreateExpression("SqlCommand", new CodePrimitiveExpression(insertCommandText), new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("sqlResourceManager"), "SqlConnection")))); } else { isCommandDeclared = true; this.Statements.Add(new CodeVariableDeclarationStatement("SqlCommand", "sqlCommand", new CodeObjectCreateExpression("SqlCommand", new CodePrimitiveExpression(insertCommandText), new CodeFieldReferenceExpression(new CodeArgumentReferenceExpression("sqlResourceManager"), "SqlConnection")))); } foreach (ColumnSchema columnSchema in this.TableSchema.Columns) { if (columnSchema.IsPersistent && columnSchema.DeclaringType == familyTable.TypeSchema) { string variableName = Generate.CamelCase(columnSchema.Name); if (familyTable.IsPrimaryKeyColumn(columnSchema)) { CodeExpression codeExpression = new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(familyTable.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), string.Format("{0}Column", columnSchema.Name))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeExpression[] { new CodeObjectCreateExpression("SqlParameter", new CodeExpression[] { new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), codeExpression }) })); } else { this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeExpression[] { new CodeObjectCreateExpression("SqlParameter", new CodeExpression[] { new CodePrimitiveExpression(string.Format("@{0}", variableName)), TypeConverter.Convert(columnSchema.DataType), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), new CodeArgumentReferenceExpression(variableName) }) })); } } } this.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression("sqlCommand"), "Parameters"), "Add", new CodeObjectCreateExpression("SqlParameter", new CodePrimitiveExpression("@rowVersion"), new CodeTypeReferenceExpression("SqlDbType.BigInt"), new CodePrimitiveExpression(0), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("ParameterDirection"), "Input"), new CodePrimitiveExpression(false), new CodePrimitiveExpression(0), new CodePrimitiveExpression(0), new CodePrimitiveExpression(null), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("DataRowVersion"), "Current"), new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(familyTable.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, familyTable.Name)), "RowVersionColumn"))))); this.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("sqlCommand"), "ExecuteNonQuery")); } } // // Autogenerated values are returned to the caller. // rowVersion = ((long)(employeeRow[ServerDataModel.Employee.RowVersionColumn])); this.Statements.Add(new CodeCommentStatement("Autogenerated values are returned to the caller.")); this.Statements.Add(new CodeAssignStatement(new CodeArgumentReferenceExpression("rowVersion"), new CodeCastExpression(typeof(long), new CodeIndexerExpression(new CodeVariableReferenceExpression(string.Format("{0}Row", Generate.CamelCase(this.TableSchema.Name))), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(string.Format("{0}.{1}", this.ServerSchema.Name, this.TableSchema.Name)), "RowVersionColumn"))))); }