예제 #1
0
        /// <summary>
        /// Implements a DataTable.
        /// </summary>
        /// <param name="tableSchema">The table schema that describes the event arguments.</param>
        public ChangeEventArgsClass(TableSchema tableSchema)
        {
            // The row change arguments are designed for this table.
            this.tableSchema = tableSchema;

            // Construct the type names for the table and rows within the table.
            string tableTypeName   = string.Format("{0}DataTable", tableSchema.Name);
            string rowTypeName     = string.Format("{0}Row", tableSchema.Name);
            string eventTypeName   = string.Format("{0}ChangeEvent", rowTypeName);
            string rowVariableName = string.Format("{0}Row", tableSchema.Name[0].ToString().ToLower() + tableSchema.Name.Remove(0, 1));

            //		/// <summary>
            //		/// Arguments for the event that indicates a change in a Department table row.
            //		/// </summary>
            //		[System.Diagnostics.DebuggerStepThrough()]
            //		public class DepartmentRowChangeEvent : EventArgs
            //		{
            CodeTypeDeclaration tableClass = new CodeTypeDeclaration();

            this.Comments.Add(new CodeCommentStatement("<summary>", true));
            this.Comments.Add(new CodeCommentStatement(string.Format("Arguments for the event that indicates a change in a {0} table row.", this.tableSchema.Name), true));
            this.Comments.Add(new CodeCommentStatement("</summary>", true));
            this.CustomAttributes.Add(new CodeAttributeDeclaration("System.Diagnostics.DebuggerStepThrough"));
            this.TypeAttributes = TypeAttributes.Public;
            this.IsClass        = true;
            this.Name           = eventTypeName;
            this.BaseTypes.Add("EventArgs");

            //			/// <summary>
            //			/// The Department row that has been changed.
            //			/// </summary>
            //			private DepartmentRow departmentRow;
            CodeMemberField tableRowField = new CodeMemberField(new CodeTypeReference(rowTypeName), rowVariableName);

            tableRowField.Attributes = MemberAttributes.Private;
            tableRowField.Comments.Add(new CodeCommentStatement("<summary>", true));
            tableRowField.Comments.Add(new CodeCommentStatement(string.Format("The {0} row that has been changed.", this.tableSchema.Name), true));
            tableRowField.Comments.Add(new CodeCommentStatement("</summary>", true));
            this.Members.Add(tableRowField);

            //			/// <summary>
            //			/// The action that caused the change to the row.
            //			/// </summary>
            //			private DataRowAction dataRowAction;
            CodeMemberField dataRowActionField = new CodeMemberField(new CodeTypeReference("DataRowAction"), "dataRowAction");

            dataRowActionField.Comments.Add(new CodeCommentStatement("<summary>", true));
            dataRowActionField.Comments.Add(new CodeCommentStatement("The action that caused the change to the row.", true));
            dataRowActionField.Comments.Add(new CodeCommentStatement("</summary>", true));
            this.Members.Add(dataRowActionField);

            //			/// <summary>
            //			/// Create the arguments for a changing Department row event.
            //			/// </summary>
            //			/// <param name="departmentRow">The Department row that has changed.</param>
            //			/// <param name="dataRowAction">The action that caused the change.</param>
            //			public DepartmentRowChangeEvent(DepartmentRow departmentRow, DataRowAction dataRowAction)
            //			{
            //				// Initialize the object.
            //				this.departmentRow = departmentRow;
            //				this.dataRowAction = dataRowAction;
            //			}
            CodeConstructor constructor = new CodeConstructor();

            this.Members.Add(constructor);
            constructor.Comments.Add(new CodeCommentStatement("<summary>", true));
            constructor.Comments.Add(new CodeCommentStatement(string.Format("Create the arguments for a changing {0} row event.", this.tableSchema.Name), true));
            constructor.Comments.Add(new CodeCommentStatement("</summary>", true));
            constructor.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">The {1} row that has changed.</param>", rowVariableName, this.tableSchema.Name), true));
            constructor.Comments.Add(new CodeCommentStatement("<param name=\"dataRowAction\">The action that caused the change.</param>", true));
            constructor.Attributes = MemberAttributes.Public;
            constructor.Parameters.Add(new CodeParameterDeclarationExpression(rowTypeName, rowVariableName));
            constructor.Parameters.Add(new CodeParameterDeclarationExpression("DataRowAction", "dataRowAction"));
            constructor.Statements.Add(new CodeCommentStatement("Initialize the object."));
            constructor.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), rowVariableName), new CodeArgumentReferenceExpression(rowVariableName)));
            constructor.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "dataRowAction"), new CodeArgumentReferenceExpression("dataRowAction")));

            //			/// <summary>
            //			/// Gets the Department row that has been changed.
            //			/// </summary>
            //			public DepartmentRow DepartmentRow
            //			{
            //				get
            //				{
            //					return this.departmentRow;
            //				}
            //			}
            CodeMemberProperty tableRowProperty = new CodeMemberProperty();

            tableRowProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            tableRowProperty.Comments.Add(new CodeCommentStatement(string.Format("Gets the {0} row that has been changed.", this.tableSchema.Name), true));
            tableRowProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            tableRowProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            tableRowProperty.Type       = new CodeTypeReference(rowTypeName);
            tableRowProperty.Name       = rowTypeName;
            tableRowProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), rowVariableName)));
            this.Members.Add(tableRowProperty);

            //			/// <summary>
            //			/// Gets the action that caused the change to the row.
            //			/// </summary>
            //			public DataRowAction Action
            //			{
            //				get
            //				{
            //					return this.dataRowAction;
            //				}
            //			}
            CodeMemberProperty actionProperty = new CodeMemberProperty();

            actionProperty.Comments.Add(new CodeCommentStatement("<summary>", true));
            actionProperty.Comments.Add(new CodeCommentStatement("Gets the action that caused the change to the row.", true));
            actionProperty.Comments.Add(new CodeCommentStatement("</summary>", true));
            actionProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            actionProperty.Type       = new CodeTypeReference("DataRowAction");
            actionProperty.Name       = "Action";
            actionProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "dataRowAction")));
            this.Members.Add(actionProperty);

            //		}
        }
예제 #2
0
        /// <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")))));
        }
예제 #3
0
        /// <summary>
        /// Generates the method used to handle the Row Changed event.
        /// </summary>
        /// <param name="tableSchema">The table to which this event belongs.</param>
        public TableAddRowMethod(TableSchema tableSchema)
        {
            // Construct the type names for the table and rows within the table.
            string rowTypeName     = string.Format("{0}Row", tableSchema.Name);
            string rowVariableName = string.Format("{0}Row", tableSchema.Name[0].ToString().ToLower() + tableSchema.Name.Remove(0, 1));

            // 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>();

            tableLockList.Add(new WriteRequest(tableSchema));
            foreach (KeyrefSchema parentKeyref in tableSchema.ParentKeyrefs)
            {
                tableLockList.Add(new ReadRequest(parentKeyref.Refer.Selector));
            }
            tableLockList.Sort();

            //			/// <summary>
            //			/// Add a Department row to the collection.
            //			/// </summary>
            //			/// <param name="departmentRow">The row to be added to the Department table.</param>
            //			public void AddDepartmentRow(DepartmentRow departmentRow)
            //			{
            //				try
            //				{
            //					// This adds a new row to the Department table.
            //					this.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite);
            //					this.Rows.Add(departmentRow);
            //				}
            //				finally
            //				{
            //					// The table can be accessed by other threads once the row is added.
            //					this.ReaderWriterLock.ReleaseWriterLock();
            //				}
            //			}
            this.Comments.Add(new CodeCommentStatement("<summary>", true));
            this.Comments.Add(new CodeCommentStatement(string.Format("Add a {0} row to the collection.", tableSchema.Name), true));
            this.Comments.Add(new CodeCommentStatement("</summary>", true));
            this.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">The row to be added to the Department table.</param>", rowVariableName), true));
            this.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            this.Name       = string.Format("Add{0}Row", tableSchema.Name);
            this.Parameters.Add(new CodeParameterDeclarationExpression(rowTypeName, rowVariableName));
            CodeTryCatchFinallyStatement tryCatchFinallyStatement = new CodeTryCatchFinallyStatement();

            tryCatchFinallyStatement.TryStatements.Add(new CodeCommentStatement(string.Format("This adds a new row to the {0} table.", tableSchema.Name)));
            foreach (LockRequest lockRequest in tableLockList)
            {
                CodeExpression tableExpression = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModelSchema.Name), lockRequest.TableSchema.Name);
                if (lockRequest is ReadRequest)
                {
                    tryCatchFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(tableExpression, "ReaderWriterLock"), "AcquireReaderLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")));
                }
                if (lockRequest is WriteRequest)
                {
                    tryCatchFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(tableExpression, "ReaderWriterLock"), "AcquireWriterLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")));
                }
            }
            tryCatchFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "Rows"), "Add", new CodeExpression[] { new CodeArgumentReferenceExpression(rowVariableName) }));
            tryCatchFinallyStatement.FinallyStatements.Add(new CodeCommentStatement("The table can be accessed by other threads once the row is added."));
            foreach (LockRequest lockRequest in tableLockList)
            {
                CodeExpression tableExpression = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tableSchema.DataModelSchema.Name), lockRequest.TableSchema.Name);
                if (lockRequest is ReadRequest)
                {
                    tryCatchFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(tableExpression, "ReaderWriterLock"), "ReleaseReaderLock"));
                }
                if (lockRequest is WriteRequest)
                {
                    tryCatchFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(tableExpression, "ReaderWriterLock"), "ReleaseWriterLock"));
                }
            }
            this.Statements.Add(tryCatchFinallyStatement);
        }
예제 #4
0
 public WriteRequest(TableSchema tableSchema) : base(tableSchema)
 {
 }
예제 #5
0
 public void Add(TableSchema tableSchema)
 {
     this.tableList.Add(tableSchema.Name, tableSchema);
 }
예제 #6
0
        static int Main(string[] args)
        {
            try
            {
                // Defaults
                ServerCompiler.name = string.Empty;
                ServerCompiler.volatileStoreName = string.Empty;
                ServerCompiler.durableStoreName  = string.Empty;
                ServerCompiler.references        = new System.Collections.Generic.List <string>();
                ServerCompiler.targetNamespace   = "DefaultNamespace";

                // The command line parser is driven by different states that are triggered by the flags read.  Unless a flag has
                // been read, the command line parser assumes that it's reading the file name from the command line.
                argumentState = ArgumentState.InputFileName;

                // Parse the command line for arguments.
                foreach (string argument in args)
                {
                    // Decode the current argument into a state change (or some other action).
                    switch (argument)
                    {
                    case "-ds":
                        argumentState = ArgumentState.DurableStore;
                        continue;

                    case "-i":
                        argumentState = ArgumentState.InputFileName;
                        continue;

                    case "-n":
                        argumentState = ArgumentState.Name;
                        continue;

                    case "-ns":
                        argumentState = ArgumentState.TargetNamespace;
                        continue;

                    case "-out":
                        argumentState = ArgumentState.OutputFileName;
                        continue;

                    case "-ref":
                        argumentState = ArgumentState.Reference;
                        continue;

                    case "-t":
                        argumentState = ArgumentState.TargetTable;
                        continue;

                    case "-vs":
                        argumentState = ArgumentState.VolatileStore;
                        continue;
                    }

                    // The parsing state will determine which variable is read next.
                    switch (argumentState)
                    {
                    case ArgumentState.DurableStore:
                        ServerCompiler.durableStoreName = argument;
                        break;

                    case ArgumentState.InputFileName:
                        ServerCompiler.inputFileName = argument;
                        break;

                    case ArgumentState.Name:
                        ServerCompiler.name = argument;
                        break;

                    case ArgumentState.OutputFileName:
                        ServerCompiler.outputFileName = argument;
                        break;

                    case ArgumentState.TargetNamespace:
                        ServerCompiler.targetNamespace = argument;
                        break;

                    case ArgumentState.TargetTable:
                        ServerCompiler.targetTableName = argument;
                        break;

                    case ArgumentState.Reference:
                        ServerCompiler.references.Add(argument);
                        break;

                    case ArgumentState.VolatileStore:
                        ServerCompiler.volatileStoreName = argument;
                        break;
                    }

                    // The default state is to look for the input file name on the command line.
                    argumentState = ArgumentState.InputFileName;
                }

                // Throw a usage message back at the user if no file name was given.
                if (inputFileName == null || outputFileName == null || name == string.Empty ||
                    volatileStoreName == string.Empty || durableStoreName == string.Empty)
                {
                    throw new Exception("Usage: Generator -i <input file name> -t <target table name>");
                }

                // Read the schema into a string.  This emulates the way that the IDE would normally call a code generator.  Create
                // the MiddleTierSchema (like a Schema, but with extra helping functions and relations for this type of code
                // generation).
                StreamReader streamReader = new StreamReader(inputFileName);
                ServerSchema serverSchema = new ServerSchema(streamReader.ReadToEnd());
                TableSchema  tableSchema  = serverSchema.Tables.Find(ServerCompiler.targetTableName);

                // Install the parameters into the schema.
                serverSchema.Name              = ServerCompiler.name;
                serverSchema.TargetNamespace   = ServerCompiler.targetNamespace;
                serverSchema.References        = ServerCompiler.references;
                serverSchema.VolatileStoreName = ServerCompiler.volatileStoreName;
                serverSchema.DurableStoreName  = ServerCompiler.durableStoreName;

                // This will generate a buffer of source code from the intput table schema.
                byte[] buffer = GenerateCode(serverSchema, tableSchema);

                // Write the buffer to the specified UTF8 output file.
                StreamWriter streamWriter = new StreamWriter(outputFileName);
                streamWriter.Write(Encoding.UTF8.GetString(buffer));
                streamWriter.Close();
            }
            catch (Exception exception)
            {
                // Write the exceptions to the console.
                Console.WriteLine(exception.Message);
            }

            // This indicates the table was compiled successfully.
            return(0);
        }
        /// <summary>
        /// Generates the method used to handle the Row Changed event.
        /// </summary>
        /// <param name="tableSchema">The table to which this event belongs.</param>
        public TableAddRowWithValuesMethod(TableSchema tableSchema)
        {
            // Construct the type names for the table and rows within the table.
            string rowTypeName = string.Format("{0}Row", tableSchema.Name);

            //			/// <summary>
            //			/// Add a Department row to the collection.
            //			/// </summary>
            //			/// <param name="departmentId">The initial value of the DepartmentId column.</param>
            //			public DepartmentRow AddDepartmentRow(int departmentId)
            //			{
            //				try
            //				{
            //					// This adds a new row to the Department table table after populating the columns with the initial data.
            //					this.ReaderWriterLock.AcquireWriterLock(System.Threading.Timeout.Infinite);
            //					DepartmentRow rowDepartmentRow = ((DepartmentRow)(this.NewRow()));
            //					rowDepartmentRow.ItemArray = new object[] {
            //							departmentId};
            //					this.Rows.Add(rowDepartmentRow);
            //					return rowDepartmentRow;
            //				}
            //				finally
            //				{
            //					// The table can be accessed by other threads once the row is added.
            //					this.ReaderWriterLock.ReleaseWriterLock();
            //				}
            //			}
            this.Comments.Add(new CodeCommentStatement("<summary>", true));
            this.Comments.Add(new CodeCommentStatement(string.Format("Add a {0} row to the collection.", tableSchema.Name), true));
            this.Comments.Add(new CodeCommentStatement("</summary>", true));
            foreach (ColumnSchema columnSchema in tableSchema.Columns)
            {
                if (columnSchema.DeclaringType == tableSchema.TypeSchema)
                {
                    if (!columnSchema.IsAutoIncrement)
                    {
                        string parameterName = string.Format("{0}", columnSchema.Name[0].ToString().ToLower() + columnSchema.Name.Remove(0, 1));
                        this.Comments.Add(new CodeCommentStatement(string.Format("<param name=\"{0}\">The initial value of the {1} column.</param>", parameterName, columnSchema.Name), true));
                    }
                }
            }
            this.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            this.ReturnType = new CodeTypeReference(rowTypeName);
            this.Name       = string.Format("Add{0}Row", tableSchema.Name);
            foreach (ColumnSchema columnSchema in tableSchema.Columns)
            {
                if (columnSchema.DeclaringType == tableSchema.TypeSchema)
                {
                    if (!columnSchema.IsAutoIncrement)
                    {
                        string parameterName = string.Format("{0}", columnSchema.Name[0].ToString().ToLower() + columnSchema.Name.Remove(0, 1));
                        this.Parameters.Add(new CodeParameterDeclarationExpression(columnSchema.DataType, parameterName));
                    }
                }
            }
            CodeTryCatchFinallyStatement tryCatchFinallyStatement = new CodeTryCatchFinallyStatement();

            tryCatchFinallyStatement.TryStatements.Add(new CodeCommentStatement(string.Format("This adds a new row to the {0} table table after populating the columns with the initial data.", tableSchema.Name)));
            tryCatchFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "ReaderWriterLock"), "AcquireWriterLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")));
            tryCatchFinallyStatement.TryStatements.Add(new CodeVariableDeclarationStatement(String.Format("{0}Row", tableSchema.Name), String.Format("row{0}Row", tableSchema.Name), new CodeCastExpression(String.Format("{0}Row", tableSchema.Name), new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "NewRow", new CodeExpression[] { }))));
            CodeExpressionCollection codeExpressionCollection = new CodeExpressionCollection();

            foreach (ColumnSchema columnSchema in tableSchema.Columns)
            {
                if (columnSchema.DeclaringType == tableSchema.TypeSchema)
                {
                    string parameterName = string.Format("{0}", columnSchema.Name[0].ToString().ToLower() + columnSchema.Name.Remove(0, 1));
                    if (columnSchema.IsAutoIncrement)
                    {
                        codeExpressionCollection.Add(new CodePrimitiveExpression(null));
                    }
                    else
                    {
                        codeExpressionCollection.Add(new CodeVariableReferenceExpression(parameterName));
                    }
                }
            }
            CodeExpression[] itemArray = new CodeExpression[codeExpressionCollection.Count];
            for (int index = 0; index < codeExpressionCollection.Count; index++)
            {
                itemArray[index] = codeExpressionCollection[index];
            }
            tryCatchFinallyStatement.TryStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeVariableReferenceExpression(string.Format("row{0}Row", tableSchema.Name)), "ItemArray"), new CodeArrayCreateExpression(typeof(System.Object), itemArray)));
            tryCatchFinallyStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "Rows"), "Add", new CodeExpression[] { new CodeArgumentReferenceExpression(string.Format("row{0}Row", tableSchema.Name)) }));
            tryCatchFinallyStatement.TryStatements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression(string.Format("row{0}Row", tableSchema.Name))));
            tryCatchFinallyStatement.FinallyStatements.Add(new CodeCommentStatement("The table can be accessed by other threads once the row is added."));
            tryCatchFinallyStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "ReaderWriterLock"), "ReleaseWriterLock"));
            this.Statements.Add(tryCatchFinallyStatement);
        }
예제 #8
0
        /// <summary>
        /// Generates a method to get a list of child rows.
        /// </summary>
        /// <param name="keyrefSchema">The foreign key that references the child table.</param>
        public RowChildRowsMethod(KeyrefSchema keyrefSchema)
        {
            // These variables are used to construct the method.
            TableSchema childTable       = keyrefSchema.Selector;
            TableSchema parentTable      = keyrefSchema.Refer.Selector;
            string      rowTypeName      = string.Format("{0}Row", childTable.Name);
            string      tableFieldName   = string.Format("table{0}", parentTable.Name);
            string      relationName     = string.Format("{0}{1}Relation", parentTable.Name, childTable.Name);
            string      childRowTypeName = string.Format("{0}Row", keyrefSchema.Selector.Name);

            // 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>();

            tableLockList.Add(new ReadRequest(childTable));
            tableLockList.Add(new ReadRequest(parentTable));
            tableLockList.Sort();

            // If the foreign keys share the same primary key, then the names of the methods will need to be decorated with the
            // key name in order to make them unique.  This will test the foreign keys for duplicate primary key names.
            bool isDuplicateKey = false;

            foreach (KeyrefSchema otherforeignKey in childTable.ChildKeyrefs)
            {
                if (otherforeignKey != keyrefSchema && otherforeignKey.Selector == keyrefSchema.Selector)
                {
                    isDuplicateKey = true;
                }
            }

            //			/// <summary>
            //			/// Gets the children rows in the Engineer table.
            //			/// </summary>
            //			public EngineerRow[] GetEngineerRows()
            //			{
            this.Comments.Add(new CodeCommentStatement("<summary>", true));
            this.Comments.Add(new CodeCommentStatement(string.Format("Gets the children rows in the {0} table.", keyrefSchema.Selector.Name), true));
            this.Comments.Add(new CodeCommentStatement("</summary>", true));
            this.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            this.ReturnType = new CodeTypeReference(childRowTypeName, 1);
            this.Name       = isDuplicateKey ? string.Format("Get{0}sBy{1}", childRowTypeName, keyrefSchema.Name) : string.Format("Get{0}s", childRowTypeName);

            //				if (this.ReaderWriterLock.IsReaderLockHeld == false && this.ReaderWriterLock.IsWriterLockHeld == false)
            //					throw new LockException("An attempt was made to access an Employee Row without a lock");
            this.Statements.Add(new CodeCommentStatement("This insures the row is locked before attempting to create a list of children."));
            this.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "ReaderWriterLock"), "IsReaderLockHeld"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(false)), CodeBinaryOperatorType.BooleanAnd, new CodeBinaryOperatorExpression(new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "ReaderWriterLock"), "IsWriterLockHeld"), CodeBinaryOperatorType.IdentityEquality, new CodePrimitiveExpression(false))),
                                                           new CodeThrowExceptionStatement(new CodeObjectCreateExpression(new CodeTypeReference("MarkThree.LockException"), new CodePrimitiveExpression(string.Format("An attempt was made to access a {0} row without a lock", parentTable.Name))))));

            //				try
            //				{
            //					// The child table must be locked to insure it doesn't change while the relation is used to create a list of
            //					// all the child rows of this row.
            //					this.tableEmployee.EmployeeEngineerRelation.ChildTable.ReaderWriterLock.AcquireReaderLock(System.Threading.Timeout.Infinite);
            //					return ((EngineerRow[])(this.GetChildRows(this.tableEmployee.EmployeeEngineerRelation)));
            //				}
            //				finally
            //				{
            //					// The child table can be released once the list is built.
            //					this.tableEmployee.EmployeeEngineerRelation.ChildTable.ReaderWriterLock.ReleaseReaderLock();
            //				}
            //			}
            CodeTryCatchFinallyStatement getTryStatement = new CodeTryCatchFinallyStatement();
            CodeExpression parentRelationExpression      = new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), tableFieldName), relationName);

            getTryStatement.TryStatements.Add(new CodeCommentStatement("The child table must be locked to insure it doesn't change while the relation is used to create a list of"));
            getTryStatement.TryStatements.Add(new CodeCommentStatement("all the child rows of this row."));
            foreach (LockRequest lockRequest in tableLockList)
            {
                getTryStatement.TryStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(keyrefSchema.Selector.DataModelSchema.Name), lockRequest.TableSchema.Name), "ReaderWriterLock"), "AcquireReaderLock", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Threading.Timeout)), "Infinite")));
            }
            getTryStatement.TryStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(new CodeTypeReference(childRowTypeName, 1), new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "GetChildRows", new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), tableFieldName), string.Format("{0}{1}Relation", keyrefSchema.Refer.Selector.Name, keyrefSchema.Selector.Name))))));
            getTryStatement.FinallyStatements.Add(new CodeCommentStatement("The child table can be released once the list is built."));
            foreach (LockRequest lockRequest in tableLockList)
            {
                getTryStatement.FinallyStatements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(keyrefSchema.Selector.DataModelSchema.Name), lockRequest.TableSchema.Name), "ReaderWriterLock"), "ReleaseReaderLock"));
            }
            this.Statements.Add(getTryStatement);
        }
예제 #9
0
        /// <summary>
        /// Generates the DDL for a table.
        /// </summary>
        /// <param name="streamWriter">The file to which the DDL is written.</param>
        /// <param name="tableSchema">The schema description of the table.</param>
        private static void GenerateTable(StreamWriter streamWriter, TableSchema tableSchema)
        {
            // Generate the prolog for this table.
            streamWriter.WriteLine("/* The {0} Table */", tableSchema.Name);

            // Generate a prolog showing the time of creation and the current version of the table for the log file.
            streamWriter.WriteLine("if not exists (select * from \"VersionControl\" where \"Name\" = '{0}')", tableSchema.Name);
            streamWriter.WriteLine("	print convert(varchar, getdate(), 120) + 'Z <Undefined>: \"{0}\" doesn''t exist in the catalogs.'", tableSchema.Name);
            streamWriter.WriteLine("else");
            streamWriter.WriteLine("begin");
            streamWriter.WriteLine("	declare @revision \"decimal\"");
            streamWriter.WriteLine("	select @revision = \"Revision\" from \"VersionControl\" where \"Name\" = '{0}'", tableSchema.Name);
            streamWriter.WriteLine("	print convert(varchar, getdate(), 120) + 'Z Table: \"{0}\", Initial revision: ' + convert(varchar, @revision)", tableSchema.Name);
            streamWriter.WriteLine("end");
            streamWriter.WriteLine();

            // The table schema is only run if the version control table indicates that the update is needed.
            streamWriter.WriteLine("/* This checks the version control table to determine if an update is needed. */");
            streamWriter.WriteLine("declare @currentRevision \"decimal\"");
            streamWriter.WriteLine("declare @requiredRevision \"decimal\"");
            streamWriter.WriteLine("select @currentRevision = isnull((select \"Revision\" from \"VersionControl\" where \"VersionControl\".\"Name\" = '{0}'), -1.0)", tableSchema.Name);
            streamWriter.WriteLine("select @requiredRevision = isnull((select \"Revision\" from \"VersionHistory\", \"VersionTag\"");
            streamWriter.WriteLine("	where \"VersionHistory\".\"Active\" = 1 and \"VersionHistory\".\"Label\" = \"VersionTag\".\"Label\" and	\"VersionTag\".\"Name\" = '{0}'), {1})", tableSchema.Name, tableSchema.DataModelSchema.Version);
            streamWriter.WriteLine("if @currentRevision < {0} and {0} <= @requiredRevision", tableSchema.DataModelSchema.Version);
            streamWriter.WriteLine("begin");
            streamWriter.WriteLine("");

            // This transaction will remove the previous version of the table and create the new version.
            streamWriter.WriteLine("	/* The revision must be completed as a unit. */");
            streamWriter.WriteLine("	begin transaction");
            streamWriter.WriteLine("");
            streamWriter.WriteLine("	/* Remove the object and any dependancies. */");
            foreach (KeyrefSchema childkeyref in tableSchema.ChildKeyrefs)
            {
                streamWriter.WriteLine("	if exists (select * from sysobjects where type = 'F' and name = '{0}')", childkeyref.Name);
                streamWriter.WriteLine("		alter table \"{0}\" drop constraint \"{1}\"", childkeyref.Selector.Name, childkeyref.Name);
            }
            streamWriter.WriteLine("	if exists (select * from sysobjects where type = 'U' and name = '{0}')", tableSchema.Name);
            streamWriter.WriteLine("		drop table \"{0}\"", tableSchema.Name);
            streamWriter.WriteLine("");

            // The table is described here.
            streamWriter.WriteLine("	/* Create the table. */");
            streamWriter.WriteLine(string.Format("	create table \"{0}\" (", tableSchema.Name));

            // Generate each of the column descriptions.
            foreach (ColumnSchema columnSchema in tableSchema.Columns)
            {
                if (columnSchema.DeclaringType == tableSchema.TypeSchema)
                {
                    streamWriter.WriteLine(string.Format("		\"{0}\" {1} {2},", columnSchema.Name, GetSqlDataType(columnSchema.DataType),
                                                         columnSchema.MinOccurs == 0 ? "null" : "not null"));
                }
            }

            // These columns are always included for house keeping.
            streamWriter.WriteLine("		\"IsArchived\" \"bit\" not null,");
            streamWriter.WriteLine("		\"IsDeleted\" \"bit\" not null,");
            streamWriter.WriteLine("		\"RowVersion\" \"bigint\" not null");

            // The table is always generated on the primary (default) device.
            streamWriter.WriteLine("	) on \"PRIMARY\"");
            streamWriter.WriteLine("");

            // Generate the keys, foreign keys and defaults on this table.
            GenerateKeys(streamWriter, tableSchema);
            GenerateIndices(streamWriter, tableSchema);
            GenerateForeignKeys(streamWriter, tableSchema);
            GenerateDefaults(streamWriter, tableSchema);

            // This will update the version control table to indicate that the table was updated to the new version.
            streamWriter.WriteLine("	/* Update the versionControl table to reflect the change. */");
            streamWriter.WriteLine("	if exists (select * from \"VersionControl\" where \"Name\" = '{0}')", tableSchema.Name);
            streamWriter.WriteLine("		update \"VersionControl\" set \"Revision\" = {0} where \"Name\" = '{1}'", tableSchema.DataModelSchema.Version, tableSchema.Name);
            streamWriter.WriteLine("	else");
            streamWriter.WriteLine("		insert \"VersionControl\" (\"Name\", \"Revision\") select '{0}', {1}", tableSchema.Name, tableSchema.DataModelSchema.Version);
            streamWriter.WriteLine("");

            // Commit or reject the changes to the table.
            streamWriter.WriteLine("	/* Commit the changes to the table. */");
            streamWriter.WriteLine("	commit transaction");
            streamWriter.WriteLine("");
            streamWriter.WriteLine("end");
            streamWriter.WriteLine("go");
            streamWriter.WriteLine("");

            // Generate the epilog for a successful update.
            streamWriter.WriteLine("if @@error = 0");
            streamWriter.WriteLine("begin");
            streamWriter.WriteLine("	declare @newRevision \"decimal\"");
            streamWriter.WriteLine("	select @newRevision = \"Revision\" from \"VersionControl\" where \"Name\" = '{0}'", tableSchema.Name);
            streamWriter.WriteLine("	print convert(varchar, getdate(), 120) + 'Z Table: \"{0}\", Final revision: ' + convert(varchar, @newRevision)", tableSchema.Name);
            streamWriter.WriteLine("end");
            streamWriter.WriteLine("else");
            streamWriter.WriteLine("begin");
            streamWriter.WriteLine("	declare @oldRevision \"decimal\"");
            streamWriter.WriteLine("	select @oldRevision = isnull((select \"Revision\" from \"VersionControl\" where \"Name\" = '{0}'), 0.0)", tableSchema.Name);
            streamWriter.WriteLine("	print convert(varchar, getdate(), 120) + 'Z Table: \"{0}\", Error upgrading from revision: ' + convert(varchar, @oldRevision)", tableSchema.Name);
            streamWriter.WriteLine("end");
            streamWriter.WriteLine("go");
            streamWriter.WriteLine("");
        }