/// <summary>
        /// Generates the 'delete' method.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="classMap">The class map.</param>
        public override void GenerateDelete(StreamWriter file, IClassMap classMap)
        {
            ArrayList primaryColumns = classMap.GetTableMap().GetPrimaryKeyColumnMaps();

            bool          first      = true;
            StringBuilder whereQuery = new StringBuilder(16 * primaryColumns.Count);

            foreach (IColumnMap columnMap in primaryColumns)
            {
                IPropertyMap propertyMap = classMap.GetPropertyMapForColumnMap(columnMap);

                if (!first)
                {
                    whereQuery.Append("AND ");
                }

                whereQuery
                .Append('`')
                .Append(columnMap.Name)
                .Append("`='\" + m_state.EscapeString(")
                .Append("obj." + propertyMap.Name)
                .Append(".ToString()) + \"'");

                first = false;
            }

            string sqlCommand = "DELETE FROM `" + classMap.GetTableMap().Name + "`"
                                + " WHERE " + whereQuery.ToString();

            file.WriteLine("			m_state.ExecuteNonQuery(");
            file.WriteLine("				\""+ sqlCommand + "\");");
        }
        /// <summary>
        /// Generates the 'find by' method.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="propertyMaps">The property maps.</param>
        /// <param name="returnedClassMap">The returned class map.</param>
        public override void GenerateFindBy(StreamWriter file, IList <IPropertyMap> propertyMaps, IClassMap returnedClassMap)
        {
            ArrayList allColumns = returnedClassMap.GetTableMap().ColumnMaps;

            // build the 'where' statement
            bool          first      = true;
            StringBuilder whereQuery = new StringBuilder(16 * propertyMaps.Count);

            foreach (IPropertyMap propertyMap in propertyMaps)
            {
                if (!first)
                {
                    whereQuery.Append(" AND ");
                }

                whereQuery
                .Append('`')
                .Append(propertyMap.GetColumnMap().Name)
                .Append("`='\" + m_state.EscapeString(")
                .Append(ClassUtility.GetParamName(propertyMap))
                .Append(".ToString()) + \"'");

                first = false;
            }

            string entityClassName = EntityGenerator.GetTypeName(returnedClassMap);
            string sqlCommand      = "SELECT  \" + c_rowFields + \""
                                     + " FROM `" + returnedClassMap.GetTableMap().Name + "`"
                                     + " WHERE " + whereQuery.ToString();

            // create an array and store results
            file.WriteLine("			"+ entityClassName + " entity;");
            file.WriteLine("			List<"+ entityClassName + "> results = null;");
            file.WriteLine();
            file.WriteLine("			m_state.ExecuteQuery(");
            file.WriteLine("				\""+ sqlCommand + "\",");
            file.WriteLine("				CommandBehavior.Default,");
            file.WriteLine("				delegate(MySqlDataReader reader)");
            file.WriteLine("				{");
            file.WriteLine("					results = new List<"+ entityClassName + ">(reader.FieldCount);");
            file.WriteLine("					while (reader.Read())");
            file.WriteLine("					{");
            file.WriteLine("						entity = new "+ entityClassName + "();");
            file.WriteLine("						FillEntityWithRow(ref entity, reader);");
            file.WriteLine("						results.Add(entity);");
            file.WriteLine("					}");
            file.WriteLine("				}");
            file.WriteLine("			);");
            file.WriteLine();
            file.WriteLine("			return results;");
        }
        /// <summary>
        /// Generates the 'select all' method.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="classMap">The class map.</param>
        public override void GenerateSelectAll(StreamWriter file, IClassMap classMap)
        {
            string sqlCommand      = "SELECT \" + c_rowFields + \" FROM `" + classMap.GetTableMap().Name + "`";
            string entityClassName = EntityGenerator.GetTypeName(classMap);

            // create an array and store results
            file.WriteLine("			"+ entityClassName + " entity;");
            file.WriteLine("			List<"+ entityClassName + "> results = null;");
            file.WriteLine();
            file.WriteLine("			m_state.ExecuteQuery(");
            file.WriteLine("				\""+ sqlCommand + "\",");
            file.WriteLine("				CommandBehavior.Default,");
            file.WriteLine("				delegate(MySqlDataReader reader)");
            file.WriteLine("				{");
            file.WriteLine("					results = new List<"+ entityClassName + ">();");
            file.WriteLine("					while (reader.Read())");
            file.WriteLine("					{");
            file.WriteLine("						entity = new "+ entityClassName + "();");
            file.WriteLine("						FillEntityWithRow(ref entity, reader);");
            file.WriteLine("						results.Add(entity);");
            file.WriteLine("					}");
            file.WriteLine("				}");
            file.WriteLine("			);");
            file.WriteLine();
            file.WriteLine("			return results;");
        }
        /// <summary>
        /// Generates all the 'find' methods of this interface.
        /// </summary>
        /// <param name="classMap">The class map.</param>
        /// <param name="file">The file.</param>
        private static void GenerateFindMethods(IClassMap classMap, StreamWriter file)
        {
            // method name
            file.Write("		"+ EntityGenerator.GetTypeName(classMap) + " Find(");
            ArrayList primaryColumns = classMap.GetTableMap().GetPrimaryKeyColumnMaps();

            // method's params
            bool first = true;

            foreach (IColumnMap columnMap in primaryColumns)
            {
                IPropertyMap propertyMap = classMap.GetPropertyMapForColumnMap(columnMap);

                if (!first)
                {
                    file.Write(", ");
                }

                // param type and name
                string paramName = ClassUtility.GetParamName(propertyMap);
                string paramType = ClassUtility.ConvertColumnTypeToCsType(columnMap.DataType);
                file.Write(paramType + " " + paramName);
                first = false;
            }
            file.Write(");");

            file.WriteLine();
        }
		/// <summary>
		/// Generates custom fields and methods of the class.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="classMap">The class map.</param>
		public override void GenerateCustomFieldsAndMethods(StreamWriter file, IClassMap classMap)
		{
			ArrayList		allColumns = classMap.GetTableMap().ColumnMaps;
			IColumnMap[]	allColumnsTyped = (IColumnMap[]) allColumns.ToArray(typeof (IColumnMap));
			string			columnNames = StringUtility.CombineObjects(allColumnsTyped, MapToStringConverters.Columns).ToString();

			file.WriteLine("		protected static readonly string c_rowFields = \"" + columnNames + "\";");
			
			base.GenerateCustomFieldsAndMethods(file, classMap);
		}
        /// <summary>
        /// Generates custom fields and methods of the class.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="classMap">The class map.</param>
        public override void GenerateCustomFieldsAndMethods(StreamWriter file, IClassMap classMap)
        {
            ArrayList allColumns = classMap.GetTableMap().ColumnMaps;

            IColumnMap[] allColumnsTyped = (IColumnMap[])allColumns.ToArray(typeof(IColumnMap));
            string       columnNames     = StringUtility.CombineObjects(allColumnsTyped, MapToStringConverters.Columns).ToString();

            file.WriteLine("		protected static readonly string c_rowFields = \""+ columnNames + "\";");

            base.GenerateCustomFieldsAndMethods(file, classMap);
        }
        /// <summary>
        /// Generates the 'count by' method.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="propertyMaps">The property maps.</param>
        /// <param name="returnedClassMap">The returned class map.</param>
        public override void GenerateCountBy(StreamWriter file, IList <IPropertyMap> propertyMaps, IClassMap returnedClassMap)
        {
            ArrayList allColumns = returnedClassMap.GetTableMap().ColumnMaps;

            // build the 'where' statement
            bool          first      = true;
            StringBuilder whereQuery = new StringBuilder(16 * propertyMaps.Count);

            foreach (IPropertyMap propertyMap in propertyMaps)
            {
                if (!first)
                {
                    whereQuery.Append(" AND ");
                }

                whereQuery
                .Append('`')
                .Append(propertyMap.GetColumnMap().Name)
                .Append("`='\" + m_state.EscapeString(")
                .Append(ClassUtility.GetParamName(propertyMap))
                .Append(".ToString()) + \"'");

                first = false;
            }

            string entityClassName = EntityGenerator.GetTypeName(returnedClassMap);
            string sqlCommand      = "SELECT  count(*)"
                                     + " FROM `" + returnedClassMap.GetTableMap().Name + "`"
                                     + " WHERE " + whereQuery.ToString();

            // create an array and store results
            file.WriteLine();
            file.WriteLine("			return (long) m_state.ExecuteScalar(");
            file.WriteLine("				\""+ sqlCommand + "\");");
            file.WriteLine();
        }
        /// <summary>
        /// Generates the 'create' method.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="classMap">The class map.</param>
        public override void GenerateCreate(StreamWriter file, IClassMap classMap)
        {
            bool first = true;

            // create fields list
            StringBuilder valuesQuery = new StringBuilder(16 * classMap.PropertyMaps.Count);

            foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
            {
                if (!first)
                {
                    valuesQuery.Append(",");
                }

                valuesQuery.Append("'\" + m_state.EscapeString(obj." + propertyMap.Name + ".ToString()) + \"'");

                first = false;
            }

            string sqlCommand = "INSERT INTO `" + classMap.GetTableMap().Name + "`"
                                + " VALUES (" + valuesQuery + ");";

            // find auto_incremented values
            IPropertyMap autoIncrementProperty = null;

            foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
            {
                IColumnMap columnMap = propertyMap.GetColumnMap();
                if (columnMap.IsAutoIncrease)
                {
                    // just one auto_increment column
                    autoIncrementProperty = propertyMap;
                    break;
                }
            }

            file.WriteLine("			m_state.ExecuteNonQuery(");
            file.WriteLine("				\""+ sqlCommand + "\");");

            if (autoIncrementProperty != null)
            {
                file.WriteLine("			object insertedId = m_state.ExecuteScalar(\"SELECT LAST_INSERT_ID();\");");
                file.WriteLine("			obj."+ autoIncrementProperty.Name + " = (" + ClassUtility.ConvertColumnTypeToCsType(autoIncrementProperty.GetColumnMap().DataType) + ") (long) insertedId;");
            }
        }
        /// <summary>
        /// Generates the 'find' method.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="classMap">The class map.</param>
        public override void GenerateFind(StreamWriter file, IClassMap classMap)
        {
            ArrayList primaryColumns = classMap.GetTableMap().GetPrimaryKeyColumnMaps();

            StringBuilder whereQuery = new StringBuilder();
            StringBuilder findParams = new StringBuilder();
            bool          first      = true;

            foreach (IColumnMap primColumn in primaryColumns)
            {
                IPropertyMap propertyMap = classMap.GetPropertyMapForColumnMap(primColumn);

                if (!first)
                {
                    whereQuery.Append(", ");
                    findParams.Append(", ");
                }

                whereQuery
                .Append('`')
                .Append(primColumn.Name)
                .Append("`='\" + m_state.EscapeString(")
                .Append(ClassUtility.GetParamName(propertyMap))
                .Append(".ToString()) + \"'");

                string paramName = ClassUtility.GetParamName(propertyMap);
                string paramType = ClassUtility.ConvertColumnTypeToCsType(primColumn.DataType);

                findParams.Append(paramType + " " + paramName);

                first = false;
            }

            string entityClassName = EntityGenerator.GetTypeName(classMap);
            string sqlCommand      = "SELECT \" + c_rowFields + \""
                                     + " FROM `" + classMap.GetTableMap().Name + "`"
                                     + " WHERE " + whereQuery.ToString();

            file.WriteLine("		public virtual "+ entityClassName + " Find(" + findParams.ToString() + ")");
            file.WriteLine("		{");
            file.WriteLine("			"+ entityClassName + " result = new " + entityClassName + "();");
            file.WriteLine("			string command = \""+ sqlCommand + "\";");
            file.WriteLine();
            file.WriteLine("			m_state.ExecuteQuery(");
            file.WriteLine("				command,");
            file.WriteLine("				CommandBehavior.SingleRow,");
            file.WriteLine("				delegate(MySqlDataReader reader)");
            file.WriteLine("				{");
            file.WriteLine("					if (!reader.Read())");
            file.WriteLine("					{");
            file.WriteLine("						result = null;");
            file.WriteLine("					}");
            file.WriteLine("					else");
            file.WriteLine("					{");
            file.WriteLine("						FillEntityWithRow(ref result, reader);");
            file.WriteLine("					}");
            file.WriteLine("				}");
            file.WriteLine("			);");
            file.WriteLine();
            file.WriteLine("			return result;");
            file.WriteLine("		}");
            file.WriteLine();
        }
		/// <summary>
		/// Generates the 'verify schema' code.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="classMap">The class map.</param>
		public override void GenerateVerifySchema(StreamWriter file, IClassMap classMap)
		{
#warning TODO: finish VerifySchema method
			if (classMap.PropertyMaps.Count <= 0)
			{
				file.WriteLine("			return null; // no property maps");
				return; // ???
			}
			
			// no table - create it
			bool firstColumn = true;
			StringBuilder sqlCommandText = new StringBuilder("\"CREATE TABLE IF NOT EXISTS `" + classMap.Table + "` (\"", classMap.PropertyMaps.Count * 16);
			foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
			{
				IColumnMap columnMap = propertyMap.GetColumnMap();

				// close prev statement's quote, start new line
				if (firstColumn)
				{
					sqlCommandText.Append("\n");
					firstColumn = false;
				}
				else
				{
					sqlCommandText.Append(",\"\n");
				}

				// opening quote
				sqlCommandText.Append("				+\"");

				
				// build one field creation statement
				sqlCommandText
					.Append("`")
					.Append(columnMap.Name)
					.Append("` ")
					.Append(MySqlUtility.GetDataType(columnMap));

				// is nulls allowed
				if (!columnMap.AllowNulls)
				{
					sqlCommandText.Append(" NOT NULL");
				}

				// default value
				if (columnMap.DefaultValue != null && columnMap.DefaultValue.Length > 0)
				{
					sqlCommandText
						.Append(" default '")
						.Append(MySqlUtility.Escape(columnMap.DefaultValue))
						.Append("'");
				}
				
				// auto_increment?
				if (columnMap.IsAutoIncrease)
				{
					sqlCommandText.Append(" auto_increment");
				}
			}

			// close last statement's quotes, start new line
			sqlCommandText.Append("\"\n");

			// primary keys
			ArrayList		primaryKeyMaps = classMap.GetTableMap().GetPrimaryKeyColumnMaps();
			if (primaryKeyMaps.Count > 0)
			{
				// opening quote
				sqlCommandText.Append("				+\"");
				
				// write primary key name and open fields list
				string pkName = StringUtility.CombineObjects((IColumnMap[])primaryKeyMaps.ToArray(typeof(IColumnMap)), MapToStringConverters.Join).ToString();
				sqlCommandText.Append(", primary key `" + pkName + "`");

				// combine primary key fields
				IColumnMap[]	primaryKeyMapsTyped = (IColumnMap[])primaryKeyMaps.ToArray(typeof(IColumnMap));
				StringBuilder	primaryKeyMapNames = StringUtility.CombineObjects(primaryKeyMapsTyped, MapToStringConverters.Columns);

				sqlCommandText.Append(" (");
				sqlCommandText.Append(primaryKeyMapNames);
				sqlCommandText.Append(")\"\n");
			}
			else
			{
				// no primary
//				sqlCommandText.Append("\n");
			}
			
			// close the field list
			sqlCommandText.Append("				+\")\"");

			
			
			// write to file
			file.WriteLine("			m_state.ExecuteNonQuery(" + sqlCommandText.ToString() + "\n			);");
			file.WriteLine("			m_state.ExecuteNonQuery(\"OPTIMIZE TABLE `" + classMap.GetTableMap().Name + "`\");");
			file.WriteLine("			return null;");
		}
		/// <summary>
		/// Generates the 'count all' method.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="classMap">The class map.</param>
		public override void GenerateCountAll(StreamWriter file, IClassMap classMap)
		{
			string sqlCommand = "SELECT COUNT(*) FROM `" + classMap.GetTableMap().Name + "`";

			file.WriteLine("			return (long) m_state.ExecuteScalar(\"" + sqlCommand + "\");");
		}
		/// <summary>
		/// Generates the 'select all' method.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="classMap">The class map.</param>
		public override void GenerateSelectAll(StreamWriter file, IClassMap classMap)
		{
			string sqlCommand = "SELECT \" + c_rowFields + \" FROM `" + classMap.GetTableMap().Name + "`";
			string entityClassName = EntityGenerator.GetTypeName(classMap);

			// create an array and store results
			file.WriteLine("			" + entityClassName + " entity;");
			file.WriteLine("			List<" + entityClassName + "> results = null;");
			file.WriteLine();
			file.WriteLine("			m_state.ExecuteQuery(");
			file.WriteLine("				\"" + sqlCommand + "\",");
			file.WriteLine("				CommandBehavior.Default,");
			file.WriteLine("				delegate(MySqlDataReader reader)");
			file.WriteLine("				{");
			file.WriteLine("					results = new List<" + entityClassName + ">();");
			file.WriteLine("					while (reader.Read())");
			file.WriteLine("					{");
			file.WriteLine("						entity = new " + entityClassName + "();");
			file.WriteLine("						FillEntityWithRow(ref entity, reader);");
			file.WriteLine("						results.Add(entity);");
			file.WriteLine("					}");
			file.WriteLine("				}");
			file.WriteLine("			);");
			file.WriteLine();
			file.WriteLine("			return results;");
		}
		/// <summary>
		/// Generates the 'delete' method.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="classMap">The class map.</param>
		public override void GenerateDelete(StreamWriter file, IClassMap classMap)
		{
			ArrayList primaryColumns = classMap.GetTableMap().GetPrimaryKeyColumnMaps();

			bool first = true;
			StringBuilder whereQuery = new StringBuilder(16 * primaryColumns.Count);

			foreach (IColumnMap columnMap in primaryColumns)
			{
				IPropertyMap propertyMap = classMap.GetPropertyMapForColumnMap(columnMap);
				
				if (!first)
				{
					whereQuery.Append("AND ");
				}

				whereQuery
					.Append('`')
					.Append(columnMap.Name)
					.Append("`='\" + m_state.EscapeString(")
					.Append("obj." + propertyMap.Name)
					.Append(".ToString()) + \"'");

				first = false;
			}

			string sqlCommand = "DELETE FROM `" + classMap.GetTableMap().Name + "`"
				+ " WHERE " + whereQuery.ToString();

			file.WriteLine("			m_state.ExecuteNonQuery(");
			file.WriteLine("				\"" + sqlCommand + "\");");
		}
		/// <summary>
		/// Generates the 'create' method.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="classMap">The class map.</param>
		public override void GenerateCreate(StreamWriter file, IClassMap classMap)
		{
			bool first = true;

			// create fields list
			StringBuilder valuesQuery = new StringBuilder(16 * classMap.PropertyMaps.Count);
			foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
			{
				if (!first)
				{
					valuesQuery.Append(",");
				}

				valuesQuery.Append("'\" + m_state.EscapeString(obj." + propertyMap.Name + ".ToString()) + \"'");
				
				first = false;
			}

			string sqlCommand = "INSERT INTO `" + classMap.GetTableMap().Name + "`"
				+ " VALUES (" + valuesQuery + ");";
			
			// find auto_incremented values
			IPropertyMap autoIncrementProperty = null;
			foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
			{
				IColumnMap columnMap = propertyMap.GetColumnMap();
				if (columnMap.IsAutoIncrease)
				{
					// just one auto_increment column
					autoIncrementProperty = propertyMap;
					break;
				}
			}

			file.WriteLine("			m_state.ExecuteNonQuery(");
			file.WriteLine("				\"" + sqlCommand + "\");");
			
			if (autoIncrementProperty != null)
			{
				file.WriteLine("			object insertedId = m_state.ExecuteScalar(\"SELECT LAST_INSERT_ID();\");");
				file.WriteLine("			obj." + autoIncrementProperty.Name + " = (" + ClassUtility.ConvertColumnTypeToCsType(autoIncrementProperty.GetColumnMap().DataType) + ") (long) insertedId;");
			}
		}
		/// <summary>
		/// Generates the 'count by' method.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="propertyMaps">The property maps.</param>
		/// <param name="returnedClassMap">The returned class map.</param>
		public override void GenerateCountBy(StreamWriter file, IList<IPropertyMap> propertyMaps, IClassMap returnedClassMap)
		{
			ArrayList allColumns = returnedClassMap.GetTableMap().ColumnMaps;

			// build the 'where' statement
			bool first = true;
			StringBuilder whereQuery = new StringBuilder(16 * propertyMaps.Count);
			foreach (IPropertyMap propertyMap in propertyMaps)
			{
				if (!first)
				{
					whereQuery.Append(" AND ");
				}

				whereQuery
					.Append('`')
					.Append(propertyMap.GetColumnMap().Name)
					.Append("`='\" + m_state.EscapeString(")
					.Append(ClassUtility.GetParamName(propertyMap))
					.Append(".ToString()) + \"'");

				first = false;
			}

			string entityClassName = EntityGenerator.GetTypeName(returnedClassMap);
			string sqlCommand = "SELECT  count(*)"
				+ " FROM `" + returnedClassMap.GetTableMap().Name + "`"
				+ " WHERE " + whereQuery.ToString();

			// create an array and store results
			file.WriteLine();
			file.WriteLine("			return (long) m_state.ExecuteScalar(");
			file.WriteLine("				\"" + sqlCommand + "\");");
			file.WriteLine();
		}
		/// <summary>
		/// Generates the 'find by' method.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="propertyMaps">The property maps.</param>
		/// <param name="returnedClassMap">The returned class map.</param>
		public override void GenerateFindBy(StreamWriter file, IList<IPropertyMap> propertyMaps, IClassMap returnedClassMap)
		{
			ArrayList allColumns = returnedClassMap.GetTableMap().ColumnMaps;
			
			// build the 'where' statement
			bool first = true;
			StringBuilder whereQuery = new StringBuilder(16 * propertyMaps.Count);
			foreach (IPropertyMap propertyMap in propertyMaps)
			{
				if (!first)
				{
					whereQuery.Append(" AND ");
				}

				whereQuery
					.Append('`')
					.Append(propertyMap.GetColumnMap().Name)
					.Append("`='\" + m_state.EscapeString(")
					.Append(ClassUtility.GetParamName(propertyMap))
					.Append(".ToString()) + \"'");
				
				first = false;
			}

			string entityClassName = EntityGenerator.GetTypeName(returnedClassMap);
			string sqlCommand = "SELECT  \" + c_rowFields + \""
				+ " FROM `" + returnedClassMap.GetTableMap().Name + "`"
				+ " WHERE " + whereQuery.ToString();

			// create an array and store results
			file.WriteLine("			" + entityClassName + " entity;");
			file.WriteLine("			List<" + entityClassName + "> results = null;");
			file.WriteLine();
			file.WriteLine("			m_state.ExecuteQuery(");
			file.WriteLine("				\"" + sqlCommand + "\",");
			file.WriteLine("				CommandBehavior.Default,");
			file.WriteLine("				delegate(MySqlDataReader reader)");
			file.WriteLine("				{");
			file.WriteLine("					results = new List<" + entityClassName + ">(reader.FieldCount);");
			file.WriteLine("					while (reader.Read())");
			file.WriteLine("					{");
            file.WriteLine("						entity = new " + entityClassName + "();");
			file.WriteLine("						FillEntityWithRow(ref entity, reader);");
			file.WriteLine("						results.Add(entity);");
			file.WriteLine("					}");
			file.WriteLine("				}");
			file.WriteLine("			);");
			file.WriteLine();
			file.WriteLine("			return results;");
		}
		/// <summary>
		/// Generates the 'find' method.
		/// </summary>
		/// <param name="file">The file.</param>
		/// <param name="classMap">The class map.</param>
		public override void GenerateFind(StreamWriter file, IClassMap classMap)
		{
			ArrayList primaryColumns = classMap.GetTableMap().GetPrimaryKeyColumnMaps();

			StringBuilder whereQuery = new StringBuilder();
			StringBuilder findParams = new StringBuilder();
			bool first = true;

			foreach (IColumnMap primColumn in primaryColumns)
			{
				IPropertyMap propertyMap = classMap.GetPropertyMapForColumnMap(primColumn);

				if (!first)
				{
					whereQuery.Append(", ");
					findParams.Append(", ");
				}

				whereQuery
					.Append('`')
					.Append(primColumn.Name)
					.Append("`='\" + m_state.EscapeString(")
					.Append(ClassUtility.GetParamName(propertyMap))
					.Append(".ToString()) + \"'");

				string paramName = ClassUtility.GetParamName(propertyMap);
				string paramType = ClassUtility.ConvertColumnTypeToCsType(primColumn.DataType);
					
				findParams.Append(paramType + " " + paramName);

				first = false;
			}
			
			string entityClassName = EntityGenerator.GetTypeName(classMap);
			string sqlCommand = "SELECT \" + c_rowFields + \""
				+ " FROM `" + classMap.GetTableMap().Name + "`"
				+ " WHERE " + whereQuery.ToString();

			file.WriteLine("		public virtual " + entityClassName + " Find(" + findParams.ToString() + ")");
			file.WriteLine("		{");
			file.WriteLine("			" + entityClassName + " result = new " + entityClassName + "();");
			file.WriteLine("			string command = \"" + sqlCommand + "\";");
			file.WriteLine();
			file.WriteLine("			m_state.ExecuteQuery(");
			file.WriteLine("				command,");
			file.WriteLine("				CommandBehavior.SingleRow,");
			file.WriteLine("				delegate(MySqlDataReader reader)");
			file.WriteLine("				{");
			file.WriteLine("					if (!reader.Read())");
			file.WriteLine("					{");
			file.WriteLine("						result = null;");
			file.WriteLine("					}");
			file.WriteLine("					else");
			file.WriteLine("					{");
			file.WriteLine("						FillEntityWithRow(ref result, reader);");
			file.WriteLine("					}");
			file.WriteLine("				}");
			file.WriteLine("			);");
			file.WriteLine();
			file.WriteLine("			return result;");
			file.WriteLine("		}");
			file.WriteLine();
		}
        /// <summary>
        /// Generates the 'verify schema' code.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="classMap">The class map.</param>
        public override void GenerateVerifySchema(StreamWriter file, IClassMap classMap)
        {
#warning TODO: finish VerifySchema method
            if (classMap.PropertyMaps.Count <= 0)
            {
                file.WriteLine("			return null; // no property maps");
                return;                 // ???
            }

            // no table - create it
            bool          firstColumn    = true;
            StringBuilder sqlCommandText = new StringBuilder("\"CREATE TABLE IF NOT EXISTS `" + classMap.Table + "` (\"", classMap.PropertyMaps.Count * 16);
            foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
            {
                IColumnMap columnMap = propertyMap.GetColumnMap();

                // close prev statement's quote, start new line
                if (firstColumn)
                {
                    sqlCommandText.Append("\n");
                    firstColumn = false;
                }
                else
                {
                    sqlCommandText.Append(",\"\n");
                }

                // opening quote
                sqlCommandText.Append("				+\"");


                // build one field creation statement
                sqlCommandText
                .Append("`")
                .Append(columnMap.Name)
                .Append("` ")
                .Append(MySqlUtility.GetDataType(columnMap));

                // is nulls allowed
                if (!columnMap.AllowNulls)
                {
                    sqlCommandText.Append(" NOT NULL");
                }

                // default value
                if (columnMap.DefaultValue != null && columnMap.DefaultValue.Length > 0)
                {
                    sqlCommandText
                    .Append(" default '")
                    .Append(MySqlUtility.Escape(columnMap.DefaultValue))
                    .Append("'");
                }

                // auto_increment?
                if (columnMap.IsAutoIncrease)
                {
                    sqlCommandText.Append(" auto_increment");
                }
            }

            // close last statement's quotes, start new line
            sqlCommandText.Append("\"\n");

            // primary keys
            ArrayList primaryKeyMaps = classMap.GetTableMap().GetPrimaryKeyColumnMaps();
            if (primaryKeyMaps.Count > 0)
            {
                // opening quote
                sqlCommandText.Append("				+\"");

                // write primary key name and open fields list
                string pkName = StringUtility.CombineObjects((IColumnMap[])primaryKeyMaps.ToArray(typeof(IColumnMap)), MapToStringConverters.Join).ToString();
                sqlCommandText.Append(", primary key `" + pkName + "`");

                // combine primary key fields
                IColumnMap[]  primaryKeyMapsTyped = (IColumnMap[])primaryKeyMaps.ToArray(typeof(IColumnMap));
                StringBuilder primaryKeyMapNames  = StringUtility.CombineObjects(primaryKeyMapsTyped, MapToStringConverters.Columns);

                sqlCommandText.Append(" (");
                sqlCommandText.Append(primaryKeyMapNames);
                sqlCommandText.Append(")\"\n");
            }
            else
            {
                // no primary
//				sqlCommandText.Append("\n");
            }

            // close the field list
            sqlCommandText.Append("				+\")\"");



            // write to file
            file.WriteLine("			m_state.ExecuteNonQuery("+ sqlCommandText.ToString() + "\n			);");
            file.WriteLine("			m_state.ExecuteNonQuery(\"OPTIMIZE TABLE `"+ classMap.GetTableMap().Name + "`\");");
            file.WriteLine("			return null;");
        }
        /// <summary>
        /// Generates the 'count all' method.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="classMap">The class map.</param>
        public override void GenerateCountAll(StreamWriter file, IClassMap classMap)
        {
            string sqlCommand = "SELECT COUNT(*) FROM `" + classMap.GetTableMap().Name + "`";

            file.WriteLine("			return (long) m_state.ExecuteScalar(\""+ sqlCommand + "\");");
        }
		/// <summary>
		/// Generates all the 'find' methods of this interface.
		/// </summary>
		/// <param name="classMap">The class map.</param>
		/// <param name="file">The file.</param>
		private static void GenerateFindMethods (IClassMap classMap, StreamWriter file)
		{				
			// method name
			file.Write("		" + EntityGenerator.GetTypeName(classMap) + " Find(");
			ArrayList primaryColumns = classMap.GetTableMap().GetPrimaryKeyColumnMaps();

			// method's params
			bool first = true;
			foreach (IColumnMap columnMap in primaryColumns)
			{
				IPropertyMap propertyMap = classMap.GetPropertyMapForColumnMap(columnMap);

				if (!first)
				{
					file.Write(", ");
				}

				// param type and name
				string paramName = ClassUtility.GetParamName(propertyMap);
				string paramType = ClassUtility.ConvertColumnTypeToCsType(columnMap.DataType);
				file.Write(paramType + " " + paramName);
				first = false;

			}
			file.Write(");");

			file.WriteLine();
		}
        public virtual void VerifyClassMap(IClassMap classMap)
        {
            bool failedSorting = false;
            IClassMap superClassMap = null;
            if (classMap.Name.Length < 1)
            {
                HandleVerifyException(classMap, "Class name must not be empty!", "Name"); // do not localize
            }

            if (classMap.ClassType == ClassType.Class || classMap.ClassType == ClassType.Default)
            {
                superClassMap = classMap.GetInheritedClassMap();
                if (superClassMap != null)
                {
                    if (!(classMap.IsLegalAsSuperClass(superClassMap)))
                    {
                        HandleVerifyException(classMap, "Inherited class '" + superClassMap.Name + "' is illegal as superclass for this class! Creates cyclic inheritance graph, which is a very serious error, potentially leading to infinite loops! No more verification of this class or its properties will be made until this error is corrected! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "InheritsClass"); // do not localize
                        return;
                    }
                }
                bool checkMappings = this.checkOrmMappings;
                if (classMap.IsAbstract)
                {
                    if (classMap.InheritanceType == InheritanceType.ConcreteTableInheritance)
                    {
                        checkMappings = false;
                    }
                }
                if (checkMappings)
                {
                    if (classMap.SourceClass.Length > 0)
                    {
                        if (classMap.GetSourceClassMap() == null)
                        {
                            HandleVerifyException(classMap, "Source class not found! (Class: '" + classMap.Name + "', Source class: '" + classMap.SourceClass + "')", "SourceClass"); // do not localize
                        }
                    }
                    else
                    {
                        if (classMap.Table.Length < 1)
                        {
                            HandleVerifyException(classMap, "Table name must not be empty! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "Table"); // do not localize
                        }
                        if (classMap.GetTableMap() == null)
                        {
                            HandleVerifyException(classMap, "Table not found! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Table: '" + classMap.Table + "')", "Table"); // do not localize
                        }
                        if (classMap.TypeColumn.Length > 0)
                        {
                            if (classMap.GetTypeColumnMap() == null)
                            {
                                HandleVerifyException(classMap, "Type column not found! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Type column: '" + classMap.TypeColumn + "')", "TypeColumn"); // do not localize
                            }
                            if (classMap.TypeValue.Length < 1)
                            {
                                HandleVerifyException(classMap, "Type column supplied but no type value! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Type column: '" + classMap.TypeColumn + "')", "TypeColumn"); // do not localize
                            }
                        }
                    }
                    if (classMap.TypeValue.Length > 0)
                    {
                        if (classMap.TypeColumn.Length < 1)
                        {
                            HandleVerifyException(classMap, "Type value supplied but no type column! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Type value: '" + classMap.TypeValue + "')", "TypeValue"); // do not localize
                        }
                        VerifyUniqueTypeValue(classMap);
                    }

                }
                if (classMap.InheritsClass.Length > 0)
                {
                    if (superClassMap == null)
                    {
                        HandleVerifyException(classMap, "Inherited class not found! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Inherited class: '" + classMap.InheritsClass + "')", "InheritsClass"); // do not localize
                    }
                }
                if (classMap.GetSortedIdentityPropertyMaps(ref failedSorting, true).Count < 1)
                {
                    HandleVerifyException(classMap, "Class must have at least one identity property! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "PropertyMaps"); // do not localize
                }
                if (failedSorting)
                {
                    HandleVerifyException(classMap, "Failed sorting identity properties due to invalid indexes! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "PropertyMaps"); // do not localize
                }
                if (classMap.IsInHierarchy())
                {
                    if (classMap.InheritanceType == InheritanceType.None)
                    {
                        HandleVerifyException(classMap, "Inheritance type must be specified for class that is part of an inheritance hierarchy! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "InheritanceType"); // do not localize
                    }
                    else
                    {
                        if (classMap.InheritanceType == InheritanceType.ConcreteTableInheritance)
                        {
                            if (superClassMap != null)
                            {
                                if (!(classMap.IsAbstract))
                                {
                                    foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps())
                                    {
                                        if (classMap.IsShadowingProperty(propertyMap))
                                        {
                                            if (propertyMap.IsIdentity)
                                            {
                                                HandleVerifyException(classMap,"Identity properties should not be shadowed! (" + GetClassType(classMap) + ": '" + classMap.Name + "', property: '" + propertyMap.Name + "')", "InheritanceType"); // do not localize
                                            }
                                        }
                                        else
                                        {
                                            if (!(propertyMap.IsIdentity) && !(propertyMap.IsCollection))
                                            {
                                                if (classMap.IsInheritedProperty(propertyMap))
                                                {
                                                    HandleVerifyException(classMap, "Non-identity, non-collection Properties should be shadowed (at least in the mapping file) in concrete classes for 'ConcreteTableInheritance' inheritance types! (" + GetClassType(classMap) + ": '" + classMap.Name + "', property: '" + propertyMap.Name + "')", "InheritanceType"); // do not localize
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (superClassMap != null)
                            {
                                foreach (IPropertyMap propertyMap in classMap.GetAllPropertyMaps())
                                {
                                    if (classMap.IsShadowingProperty(propertyMap))
                                    {
                                        if (propertyMap.IsIdentity)
                                        {
                                            HandleVerifyException(classMap, "Identity properties should not be shadowed! (" + GetClassType(classMap) + ": '" + classMap.Name + "', property: '" + propertyMap.Name + "')", "InheritanceType"); // do not localize
                                        }
                                        else
                                        {
                                            HandleVerifyException(classMap, "Properties should not be shadowed for 'SingleTableInheritance' or 'ClassTableInheritance' inheritance types! (" + GetClassType(classMap) + ": '" + classMap.Name + "', property: '" + propertyMap.Name + "')", "InheritanceType"); // do not localize
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                }
                if (classMap.InheritanceType != InheritanceType.None)
                {
                    if (classMap.TypeValue.Length < 1)
                    {
                        HandleVerifyException(classMap, "Type value must not be empty for class in inheritance hierarchy! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Type value: '" + classMap.TypeValue + "')", "TypeValue"); // do not localize
                    }
                    if (checkMappings)
                    {
                        if (classMap.GetTypeColumnMap() == null)
                        {
                            HandleVerifyException(classMap, "Type column not found! Class in inheritance hierarchy must have a type column! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Type column: '" + classMap.TypeColumn + "')", "TypeColumn"); // do not localize
                        }
                    }
                }
                else
                {
                }

            }

            if (classMap.ClassType == ClassType.Enum)
            {
                if (classMap.InheritsClass.Length > 0)
                {
                    HandleVerifyException(classMap, "Enumerations can not inherit! (Enumeration: '" + classMap.Name + "', Inherits: '" + classMap.InheritsClass + "'", "InheritsClass"); // do not localize
                }
                if (classMap.PropertyMaps.Count > 0)
                {
                    HandleVerifyException(classMap, "Enumerations can not have properties! (Enumeration: '" + classMap.Name + "'", "PropertyMaps"); // do not localize
                }
                if (classMap.GetSortedEnumValueMaps(ref failedSorting).Count < 1)
                {
                    HandleVerifyException(classMap, "Enumeration must have at least one enumeration value! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "PropertyMaps"); // do not localize
                }
                if (failedSorting)
                {
                    HandleVerifyException(classMap, "Failed sorting enumeration values due to invalid indexes! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "PropertyMaps"); // do not localize
                }

            }
            else
            {
                if (classMap.EnumValueMaps.Count > 0)
                {
                    HandleVerifyException(classMap, "Only enumerations can have enumeration values! (" + GetClassType(classMap) + ": '" + classMap.Name + "'", "PropertyMaps"); // do not localize
                }
            }

            if (classMap.ClassType == ClassType.Interface)
            {
                if (classMap.InheritsClass.Length > 0)
                {
                    IClassMap super = classMap.GetInheritedClassMap() ;
                    if (super != null)
                    {
                        if (super.ClassType != ClassType.Interface)
                        {
                            HandleVerifyException(classMap, "Interfaces can only inherit other interfaces! (Interface: '" + classMap.Name + "', Inherits: '" + classMap.InheritsClass + "'", "InheritsClass"); // do not localize
                        }
                    }
                }
            }

            if (classMap.ClassType != ClassType.Class && classMap.ClassType != ClassType.Default)
            {
                if (classMap.Source.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Source: '" + classMap.Source + "'", "Source"); // do not localize
                }
                if (classMap.Table.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to a table in a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Table: '" + classMap.Table + "'", "Table"); // do not localize
                }
                if (classMap.TypeColumn.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to a type column in a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Type column: '" + classMap.TypeColumn + "'", "TypeColumn"); // do not localize
                }
                if (classMap.TypeValue.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to a type value in a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Type value: '" + classMap.TypeValue + "'", "TypeValue"); // do not localize
                }
                if (classMap.SourceClass.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to a class in a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Source class: '" + classMap.SourceClass + "'", "SourceClass"); // do not localize
                }
                if (classMap.DocElement.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to an element in a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Document element: '" + classMap.DocElement + "'", "DocElement"); // do not localize
                }
                if (classMap.DocParentProperty.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to a parent class property for mapping against a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Document parent property: '" + classMap.DocParentProperty + "'", "DocParentProperty"); // do not localize
                }
                if (classMap.DocRoot.Length > 0)
                {
                    HandleVerifyException(classMap, "Only classes can be mapped to a document root in a persistent data source! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Document root: '" + classMap.DocRoot + "'", "DocRoot"); // do not localize
                }

            }

            if (this.Recursive)
            {
                foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
                {
                    propertyMap.Accept(this);
                }
                foreach (ICodeMap codeMap in classMap.CodeMaps)
                {
                    codeMap.Accept(this);
                }
                foreach (IEnumValueMap enumValueMap in classMap.EnumValueMaps)
                {
                    enumValueMap.Accept(this);
                }
            }
            Hashtable hashNames = new Hashtable();
            foreach (IPropertyMap propertyMap in classMap.PropertyMaps)
            {
                if (propertyMap.Name.Length > 0)
                {
                    if (hashNames.ContainsKey(propertyMap.Name.ToLower(CultureInfo.InvariantCulture)))
                    {
                        HandleVerifyException(classMap, "Property names must not appear in duplicates! (" + GetClassType(classMap) + ": '" + classMap.Name + "', Overridable Property name: '" + propertyMap.Name + "')", "PropertyMaps"); // do not localize
                    }
                    hashNames[propertyMap.Name.ToLower(CultureInfo.InvariantCulture)] = "1";
                }
            }
            if (classMap.DomainMap.VerifyCSharpReservedWords)
            {
                if (MapBase.IsReservedCSharp(classMap.Name))
                {
                    HandleVerifyException(classMap, "Reserved word conflict! The name of this class is a reserved word in C#! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "Name"); // do not localize
                }
            }
            if (classMap.DomainMap.VerifyVbReservedWords)
            {
                if (MapBase.IsReservedVBNet(classMap.Name))
                {
                    HandleVerifyException(classMap, "Reserved word conflict! The name of this class is a reserved word in Visual Basic.NET! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "Name"); // do not localize
                }
            }
            if (classMap.DomainMap.VerifyDelphiReservedWords)
            {
                if (MapBase.IsReservedDelphi(classMap.Name))
                {
                    HandleVerifyException(classMap, "Reserved word conflict! The name of this class is a reserved word in delphi for .NET! (" + GetClassType(classMap) + ": '" + classMap.Name + "')", "Name"); // do not localize
                }
            }
        }