Dot Net

Syrinx .NET Development Blog
Need help on your project? info@syrinx.com, or toll free (888) 579-7469, press 1

Part 3 - Saving and Loading Definition Files

In this installation of my blog series I’ll cover saving and loading definition files to and from XML.

To enable the code generator to do its work and be re-usable across any application development we need to do a few things:

1.       Define Code Generation Property class that will hold the data we need to generate our SQL and class code.  For the sake of simplicity I’ll call this class CodeGeneratorProperty.

2.       Create interface to create our definition, that is, we need some UI to easily enter our properties and the data associated with them.  It has to be very easy to understand and it has to cover all of the data that we need to enter.

3.       Persist the definition, that is, be able to save and load a configuration as it is needed.

1.       The definition of the CodeGeneratorProperty class will include the following fields and corresponding properties:

        private string _propertyName;        private bool _isPrimaryKey;        private bool _isForeignKey;        private bool _includeGet;        private bool _includeSet;        private string _dataType;        private bool _isRequired;        private string _size;        private string _description; 

Within the same physical file I’ll add a CodeGeneratorPropertyList class, like so:

CodeGeneratorPropertyList: IEnumerable<CodeGeneratorProperty>

As you can see this class implements the IEnumerable<T> of Type CodeGeneratorProperty.  This will allow us to store multiple Code Generator Properties and then iterate that list as necessary.

2.       A very easy and intuitive interface for our Code Generator Properties is the data grid view.  If we add a data grid view to contain our properties, a couple of text fields to define a namespace and class name, and some buttons to Load and Save our definition files, we would end up with something like the following:

Main form with datagridview control

3.       Finally, persisting and consequently retrieving our definition can be accomplished using some straight-forward xml. Our Save Definition code would be something like the following:

        const string CODE_GENERATION_DEFINITION_FOLDER_NAME_KEY = "CodeGeneratorDefinitionFilePath";        const string CODE_GENERATION_DEFINITION_FOLDER_NAME = "CodeGeneratorDefinition";        private CodeGeneratorPropertyList _propertyList;        private void btnSaveDefinition_Click(object sender, EventArgs e)        {            try            {                CreatePropertyList();                // Create an xml file holding all of the values on the screen                // Filename is Namespace underscore Class name. xml                string fileDirectory = ConfigValues.GetString(CODE_GENERATION_DEFINITION_FOLDER_NAME_KEY);                if (fileDirectory.Length == 0)                {                    fileDirectory = string.Format("C:\\Temp\\{0}\\", CODE_GENERATION_DEFINITION_FOLDER_NAME);                }                string filename =                    string.Format("{0}{1}_{2}.xml", fileDirectory, txtNamespace.Text, txtClassName.Text);                XmlTextWriter writer = new XmlTextWriter(filename, null);                writer.Formatting = Formatting.Indented;                writer.WriteStartDocument(true);                writer.WriteStartElement("Contents");                writer.WriteElementString("Namespace", txtNamespace.Text);                writer.WriteElementString("ClassName", txtClassName.Text);                writer.WriteStartElement("Properties");                foreach (CodeGeneratorProperty property in _propertyList)                {                    writer.WriteStartElement("Property");                    writer.WriteElementString("PropertyName", property.PropertyName);                    writer.WriteElementString("IsPrimaryKey", property.IsPrimaryKey.ToString());                    writer.WriteElementString("IsForeignKey", property.IsForeignKey.ToString());                    writer.WriteElementString("IsRequired", property.IsRequired.ToString());                    writer.WriteElementString("IncludeGet", property.IncludeGet.ToString());                    writer.WriteElementString("IncludeSet", property.IncludeSet.ToString());                    writer.WriteElementString("DataType", property.DataType);                    writer.WriteElementString("Size", property.Size);                    writer.WriteElementString("Description", property.Description);                    writer.WriteEndElement(); // Property                }                writer.WriteEndElement(); // Properties                writer.WriteStartElement("ForeignKeys");                writer.WriteEndElement(); // ForeignKeys                writer.WriteEndElement(); // Contents                writer.WriteEndDocument();                writer.Close();            }            catch (Exception ex)            {                MessageBox.Show(ex.Message, "Code Generator Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);            }        }         private void CreatePropertyList()        {            _propertyList.Clear();            for (int i = 0; i < (dgvProperties.Rows.Count - 1); i++)            {                DataGridViewRow row = dgvProperties.Rows[i];                CodeGeneratorProperty property = new CodeGeneratorProperty();                if (row.Cells["PropertyName"].Value == null)                {                    throw new Exception("Property Name is required");                }                else                {                    property.PropertyName = SafeData.ConvertString(row.Cells["PropertyName"].Value.ToString());                }                if (!(row.Cells["IsPrimaryKey"].Value == null))                {                    property.IsPrimaryKey = SafeData.ConvertBoolean(row.Cells["IsPrimaryKey"].Value.ToString());                }                if (!(row.Cells["IsForeignKey"].Value == null))                {                    property.IsForeignKey = SafeData.ConvertBoolean(row.Cells["IsForeignKey"].Value.ToString());                }                if (!(row.Cells["IsRequired"].Value == null))                {                    property.IsRequired = SafeData.ConvertBoolean(row.Cells["IsRequired"].Value.ToString());                }                if (!(row.Cells["IncludeGet"].Value == null))                {                    property.IncludeGet = SafeData.ConvertBoolean(row.Cells["IncludeGet"].Value.ToString());                }                if (!(row.Cells["IncludeSet"].Value == null))                {                    property.IncludeSet = SafeData.ConvertBoolean(row.Cells["IncludeSet"].Value.ToString());                }                if (!(row.Cells["DataType"].Value == null))                {                    property.DataType = SafeData.ConvertString(row.Cells["DataType"].Value.ToString());                }                if (!(row.Cells["Size"].Value == null))                {                    property.Size = SafeData.ConvertString(row.Cells["Size"].Value.ToString());                }                if (!(row.Cells["Description"].Value == null))                {                    property.Description = SafeData.ConvertString(row.Cells["Description"].Value.ToString());                }                _propertyList.Add(property);            }        } 

The corresponding Load Definition code would then be this:

        private void btnLoadDefinition_Click(object sender, EventArgs e)        {            OpenFileDialog dialog = new OpenFileDialog();            dialog.Filter = "xml files (*.xml)|*.xml";            string fileDirectory = ConfigValues.GetString(CODE_GENERATION_DEFINITION_FOLDER_NAME_KEY);            if (fileDirectory.Length == 0)            {                fileDirectory = string.Format("C:\\Temp\\{0}\\", CODE_GENERATION_DEFINITION_FOLDER_NAME);            }            dialog.InitialDirectory = fileDirectory;            dialog.Title = "Select definition file";            string fileToOpen = string.Empty;            if (dialog.ShowDialog() == DialogResult.OK)            {                fileToOpen = dialog.FileName;            }            if (fileToOpen.Length > 0)            {                dgvProperties.Rows.Clear();                // Read a chosen xml file and populate the screen controls                XmlDocument doc = new XmlDocument();                doc.Load(fileToOpen);                txtNamespace.Text = doc.SelectSingleNode("/Contents/Namespace").InnerText;                txtClassName.Text = doc.SelectSingleNode("/Contents/ClassName").InnerText;                XmlNodeList propertiesNodeList = doc.SelectNodes("/Contents/Properties/Property");                dgvProperties.Rows.Add(propertiesNodeList.Count);                int i = 0;                foreach (XmlNode node in propertiesNodeList)                {                    DataGridViewRow row = dgvProperties.Rows[i++];                    foreach (XmlNode child in node.ChildNodes)                    {                        row.Cells[child.Name].Value = child.InnerText;                    }                }            }        } 

These methods then allow us to enter values, save them in a definition file and re-load them as needed, as seen here:

Main form with filled datagridview

That wraps it up for this installation, next we’ll look at defining, creating and persisting SQL scripts for tables based on our CodeGeneratorPropertyList using SQL Server Management Objects (SMO).

 

 

Posted: Apr 13 2008, 10:29 PM by JohnF | with no comments
Filed under: , ,

Comments

No Comments