Bookieass Posted February 16, 2009 Share Posted February 16, 2009 Hello, I need a little help Actually, I want to create a windows based tool that will contain app.config file using Visual Studio 2005 The App.Config file will details regarding connectionstringschema username/password IT will also contain two table OPC_GROUP and PARAMETERS These tables are present in the Oracle database which we connect too Now, I want to add some custom information within the App.config file The custom information holds Fields, Value; This values changes frequently My problem is how can i hold these fields and its correspoinding values in config file?????? and later able to read those information on runtime....... so as to populate the data in the oracle table Any help would be deeply appreciated Here is my tryout code <?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="SDEConnection" value="Connection to GISDatabase"/> <add key="SchemaName" value="DB"/> <add key="DBConnString" value="Server=gisdb;User ID=user;Password=pass"/> <add key="GroupTable" value="OPC_GROUP"/> <add key="ParameterTable" value="PARAMETER"/> </appSettings> <GroupTable> <GroupRow> <GroupColumn name="GroupID" columnName="GROUP_ID" value="MUM_CB"/> <GroupColumn name="Description" columnName="DESCRIPTION" value="Mumbai CB Status"/> <GroupColumn name="Parameter" columnName="PARAMETER_NAME" value="CB'@<ACTUAL STATUS>"/> <GroupColumn name="Percentage" columnName="PERCENTAGE_CHANGE" value="10"/> <GroupColumn name="Time" columnName="TIME_INTERVAL" value="60000"/> </GroupRow> <GroupRow> <GroupColumn name="GroupID" columnName="GROUP_ID" value="MUM_CB_AT"/> <GroupColumn name="Description" columnName="DESCRIPTION" value="Mumbai CB Autotrip Status"/> <GroupColumn name="Parameter" columnName="PARAMETER_NAME" value="AUTOTRIP'@<ACTUAL STATUS>"/> <GroupColumn name="Percentage" columnName="PERCENTAGE_CHANGE" value="10"/> <GroupColumn name="Time" columnName="TIME_INTERVAL" value="60000"/> </GroupRow> <GroupRow> <GroupColumn name="GroupID" columnName="GROUP_ID" value="MUM_SW"/> <GroupColumn name="Description" columnName="DESCRIPTION" value="Mumbai Switch Status"/> <GroupColumn name="Parameter" columnName="PARAMETER_NAME" value="SW'@<ACTUAL STATUS>"/> <GroupColumn name="Percentage" columnName="PERCENTAGE_CHANGE" value="10"/> <GroupColumn name="Time" columnName="TIME_INTERVAL" value="60000"/> </GroupRow> <GroupRow> <GroupColumn name="GroupID" columnName="GROUP_ID" value=""/> <GroupColumn name="Description" columnName="DESCRIPTION" value=""/> <GroupColumn name="Parameter" columnName="PARAMETER_NAME" value=""/> <GroupColumn name="Percentage" columnName="PERCENTAGE_CHANGE" value=""/> <GroupColumn name="Time" columnName="TIME_INTERVAL" value=""/> </GroupRow> </GroupTable> <ParameterTable> <ParameterRow> <ParameterColumn name="GISFeature" columnName="GIS_FEATURE_CLASS_NAME" value="CircuitBreaker"/> <ParameterColumn name="ScadaTable" columnName="SCADA_TABLE_NAME" value="CB_SCADA_EVENTS"/> <ParameterColumn name="ValueCol" columnName="VALUE_COLUMN_NAME" value="CBSTATUS_VALUE" /> <ParameterColumn name="TimestampCol" columnName="TIMESTAMP_COLUMN_NAME" value="CBSTATUS_TIME"/> <ParameterColumn name="Parameter" columnName="PARAMETER_NAME" value="CB'@<ACTUAL STATUS>"/> <ParameterColumn name="QualityCol" columnName="QUALITY_COLUMN_NAME" value="CBSTATUS_QUALITY"/> <ParameterColumn name="City" columnName="CITY" value="MUM"/> <ParameterColumn name="GISAttribute" columnName="GIS_ATTRIBUTE" value="CBSTATUS"/> <ParameterColumn name="MinVal" columnName="MINVALUE" value=""/> <ParameterColumn name="MaxVal" columnName="MAXVALUE" value=""/> <ParameterColumn name="UpdatedCol" columnName="UPDATED_COLUMN_NAME" value="CBSTATUS_UPDATED"/> </ParameterRow> <ParameterRow> <ParameterColumn name="GISFeature" columnName="GIS_FEATURE_CLASS_NAME" value="CircuitBreaker"/> <ParameterColumn name="ScadaTable" columnName="SCADA_TABLE_NAME" value="CB_SCADA_EVENTS"/> <ParameterColumn name="ValueCol" columnName="VALUE_COLUMN_NAME" value="CBAUTOTRIP_VALUE"/> <ParameterColumn name="TimestampCol" columnName="TIMESTAMP_COLUMN_NAME" value="CBAUTOTRIP_TIME"/> <ParameterColumn name="Parameter" columnName="PARAMETER_NAME" value="AUTOTRIP'@<ACTUAL STATUS>"/> <ParameterColumn name="QualityCol" columnName="QUALITY_COLUMN_NAME" value="CBAUTOTRIP_QUALITY"/> <ParameterColumn name="City" columnName="CITY" value="MUM"/> <ParameterColumn name="GISAttribute" columnName="GIS_ATTRIBUTE" value="CBAUTOTRIP"/> <ParameterColumn name="MinVal" columnName="MINVALUE" value=""/> <ParameterColumn name="MaxVal" columnName="MAXVALUE" value=""/> <ParameterColumn name="UpdatedCol" columnName="UPDATED_COLUMN_NAME" value="CBAUTOTRIP_UPDATED"/> </ParameterRow> <ParameterRow> <ParameterColumn name="GISFeature" columnName="GIS_FEATURE_CLASS_NAME" value="Switch"/> <ParameterColumn name="ScadaTable" columnName="SCADA_TABLE_NAME" value="SW_SCADA_EVENTS"/> <ParameterColumn name="ValueCol" columnName="VALUE_COLUMN_NAME" value="SWSTATUS_VALUE" datatype="number" size="4"/> <ParameterColumn name="TimestampCol" columnName="TIMESTAMP_COLUMN_NAME" value="SWSTATUS_TIME" datatype="date"/> <ParameterColumn name="Parameter" columnName="PARAMETER_NAME" value="SW'@<ACTUAL STATUS>"/> <ParameterColumn name="QualityCol" columnName="QUALITY_COLUMN_NAME" value="SWSTATUS_QUALITY" datatype="varchar2" size="255"/> <ParameterColumn name="City" columnName="CITY" value="MUM"/> <ParameterColumn name="GISAttribute" columnName="GIS_ATTRIBUTE" value="SWSTATUS"/> <ParameterColumn name="MinVal" columnName="MINVALUE" value=""/> <ParameterColumn name="MaxVal" columnName="MAXVALUE" value=""/> <ParameterColumn name="UpdatedCol" columnName="UPDATED_COLUMN_NAME" value="SWSTATUS_UPDATED" datatype="varchar2" size="1"/> </ParameterRow> <ParameterRow> <ParameterColumn name="GISFeature" columnName="GIS_FEATURE_CLASS_NAME" value=""/> <ParameterColumn name="ScadaTable" columnName="SCADA_TABLE_NAME" value=""/> <ParameterColumn name="ValueCol" columnName="VALUE_COLUMN_NAME" value=""/> <ParameterColumn name="TimestampCol" columnName="TIMESTAMP_COLUMN_NAME" value=""/> <ParameterColumn name="Parameter" columnName="PARAMETER_NAME" value=""/> <ParameterColumn name="QualityCol" columnName="QUALITY_COLUMN_NAME" value=""/> <ParameterColumn name="City" columnName="CITY" value=""/> <ParameterColumn name="GISAttribute" columnName="GIS_ATTRIBUTE" value=""/> <ParameterColumn name="MinVal" columnName="MINVALUE" value=""/> <ParameterColumn name="MaxVal" columnName="MAXVALUE" value=""/> <ParameterColumn name="UpdatedCol" columnName="UPDATED_COLUMN_NAME" value=""/> </ParameterRow> </ParameterTable> </configuration> Link to comment Share on other sites More sharing options...
0 Antaris Veteran Posted February 16, 2009 Veteran Share Posted February 16, 2009 Hi, .NET 2.0 brought about a replumbed configuration mechanism. What you could do is create a few configuration element and collection classes to handle this custom information: Firstly, we could use a column class: namespace ConsoleApplication1 { /// <summary> /// Represents a column. /// </summary> public class ColumnConfigurationElement : ConfigurationElement { #region Constants private const string CFG_NAME = "name"; private const string CFG_COLUMNNAME = "columnName"; private const string CFG_VALUE = "value"; private const string CFG_DATATYPE = "datatype"; private const string CFG_SIZE = "size"; #endregion #region Properties [ConfigurationProperty(CFG_NAME, IsKey = true, IsRequired = true)] public string Name { get { return (string)this[CFG_NAME]; } set { this[CFG_NAME] = value; } } [ConfigurationProperty(CFG_COLUMNNAME, IsKey = false, IsRequired = true)] public string ColumnName { get { return (string)this[CFG_COLUMNNAME]; } set { this[CFG_COLUMNNAME] = value; } } [ConfigurationProperty(CFG_VALUE, IsKey = false, IsRequired = false, DefaultValue = (string)null)] public string Value { get { return (string)this[CFG_VALUE]; } set { this[CFG_VALUE] = value; } } [ConfigurationProperty(CFG_DATATYPE, IsKey = false, IsRequired = false, DefaultValue = (string)null)] public string DataType { get { return (string)this[CFG_DATATYPE]; } set { this[CFG_DATATYPE] = value; } } [ConfigurationProperty(CFG_SIZE, IsKey = false, IsRequired = false, DefaultValue = 0)] public int Size { get { return (int)this[CFG_SIZE]; } set { this[CFG_SIZE] = value; } } #endregion } } This ConfigurationPropertyAttribute attribute is used by the configuration section to map xml elements to their property equivalents. For this ColumnConfigurationElement, we are specifying properties for name, columnName, value, datatype and size. These get mapped over into the properties Name, ColumnName, Value, DataType and Size. The ConfigurationPropertyAttribute applied to each property allows us to set properties like: IsKey - is this the identifying property of the element. IsRequired - is this a required property. DefaultValue - the value applied to the property where no value is specified We know that columns belong in a collection, so we create a collection to handle this: namespace ConsoleApplication1 { /// <summary> /// Represents a collection of columns. /// </summary> [ConfigurationCollection(typeof(ColumnConfigurationElement), AddItemName = "Column")] public class ColumnConfigurationElementCollection : ConfigurationElementCollection { #region Methods protected override ConfigurationElement CreateNewElement() { return new ColumnConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { /* * The column's name property (read: not ColumnName) is used to identify this element. */ return ((ColumnConfigurationElement)element).Name; } #endregion } } The beauty of the .NET Configuration system, is that all the underlying mapping is done for you. The ConfigurationCollectionAttribute attribute I have applied here tells the configuration system that it is a collection of type ColumnConfigurationElement, and the add command (used in the config file) should be called "Column", it would default to "add" if this were no present. The ConfigurationElementCollection base class requires us to implement some abstract methods: CreateNewElement - create a new instance of the containing type of the collection. GetElementKey - gets a value that uniquely identifies this instance of the containing type within the collection. Going up the tree, a row contains columns, so we need to create a configuration element for that: namespace ConsoleApplication1 { /// <summary> /// Represents an individual row. /// </summary> public class RowConfigurationElement : ConfigurationElement { #region Constants private const string CFG_COLUMNS = "Columns"; #endregion #region Properties [ConfigurationProperty(CFG_COLUMNS, IsRequired = true, IsDefaultCollection = true)] public ColumnConfigurationElementCollection Columns { get { return (ColumnConfigurationElementCollection)this[CFG_COLUMNS]; } set { this[CFG_COLUMNS] = value; } } #endregion } } We only specify one property here, which is the property that is the collection of columns. We also need a containing collection of rows: namespace ConsoleApplication1 { /// <summary> /// Represents a collection of rows. /// </summary> [ConfigurationCollection(typeof(RowConfigurationElement), AddItemName = "Row")] public class RowConfigurationElementCollection : ConfigurationElementCollection { #region Methods protected override ConfigurationElement CreateNewElement() { return new RowConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { /* * A row doesn't actually have an identifying property, so we will just return a random Guid. */ return Guid.NewGuid(); } #endregion } } I've cheated here, because a row doesn't have any identifying property, we'll just generate a random one, so I've used a guid. Rows are contained in a table, but as this is the root of the tree, we'll use a ConfigurationSection instead of a ConfigurationElement as its base: namespace ConsoleApplication1 { public class TableConfigurationSection : ConfigurationSection { #region Constants private const string CFG_ROWS = "Rows"; #endregion #region Properties [ConfigurationProperty(CFG_ROWS, IsRequired = true, IsDefaultCollection = true)] public RowConfigurationElementCollection Rows { get { return (RowConfigurationElementCollection)this[CFG_ROWS]; } set { this[CFG_ROWS] = value; } } #endregion #region Methods public static TableConfigurationSection GetConfiguration(string name) { return ConfigurationManager.GetSection(name) as TableConfigurationSection; } #endregion } } I added the static method GetConfiguration to allow us to grab the configuration section from the config file. You can then modify the configuration file to support this: <?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="GroupTable" type="ConsoleApplication1.TableConfigurationSection, ConsoleApplication1" /> <section name="ParameterTable" type="ConsoleApplication1.TableConfigurationSection, ConsoleApplication1" /> </configSections> <GroupTable> <Rows> <Row> <Columns> <Column name="Test" columnName ="TEST" value="test value" /> <Column name="Test1" columnName ="TEST1" value="test value1" /> <Column name="Test2" columnName ="TEST2" value="test value2" /> </Columns> </Row> </Rows> </GroupTable> </configuration> You will probably want to read up on custom .NET configuration files for more information. If you want a cleaner xml config, you could override the OnDeserializeUnknownElement which will pass you the element name and an instance of the underlying XmlReader used to read the config. You would need to perform your own element to property mappings though. I've included my sample project for you. ConsoleApplication1.zip Link to comment Share on other sites More sharing options...
0 Bookieass Posted February 16, 2009 Author Share Posted February 16, 2009 Thnk you so much..... would look into this because even in MSDN i was not able find the explanation also.... srrry for more trouble sample project wont open for me.... I m using vista sp1 + vs2005 neither in xp sp3 + vs2005 (updated) Link to comment Share on other sites More sharing options...
0 Bookieass Posted February 17, 2009 Author Share Posted February 17, 2009 Hi,.NET 2.0 brought about a replumbed configuration mechanism. What you could do is create a few configuration element and collection classes to handle this custom information: Firstly, we could use a column class: namespace ConsoleApplication1 { /// <summary> /// Represents a column. /// </summary> public class ColumnConfigurationElement : ConfigurationElement { #region Constants private const string CFG_NAME = "name"; private const string CFG_COLUMNNAME = "columnName"; private const string CFG_VALUE = "value"; private const string CFG_DATATYPE = "datatype"; private const string CFG_SIZE = "size"; #endregion #region Properties [ConfigurationProperty(CFG_NAME, IsKey = true, IsRequired = true)] public string Name { get { return (string)this[CFG_NAME]; } set { this[CFG_NAME] = value; } } [ConfigurationProperty(CFG_COLUMNNAME, IsKey = false, IsRequired = true)] public string ColumnName { get { return (string)this[CFG_COLUMNNAME]; } set { this[CFG_COLUMNNAME] = value; } } [ConfigurationProperty(CFG_VALUE, IsKey = false, IsRequired = false, DefaultValue = (string)null)] public string Value { get { return (string)this[CFG_VALUE]; } set { this[CFG_VALUE] = value; } } [ConfigurationProperty(CFG_DATATYPE, IsKey = false, IsRequired = false, DefaultValue = (string)null)] public string DataType { get { return (string)this[CFG_DATATYPE]; } set { this[CFG_DATATYPE] = value; } } [ConfigurationProperty(CFG_SIZE, IsKey = false, IsRequired = false, DefaultValue = 0)] public int Size { get { return (int)this[CFG_SIZE]; } set { this[CFG_SIZE] = value; } } #endregion } } This ConfigurationPropertyAttribute attribute is used by the configuration section to map xml elements to their property equivalents. For this ColumnConfigurationElement, we are specifying properties for name, columnName, value, datatype and size. These get mapped over into the properties Name, ColumnName, Value, DataType and Size. The ConfigurationPropertyAttribute applied to each property allows us to set properties like: IsKey - is this the identifying property of the element. IsRequired - is this a required property. DefaultValue - the value applied to the property where no value is specified We know that columns belong in a collection, so we create a collection to handle this: namespace ConsoleApplication1 { /// <summary> /// Represents a collection of columns. /// </summary> [ConfigurationCollection(typeof(ColumnConfigurationElement), AddItemName = "Column")] public class ColumnConfigurationElementCollection : ConfigurationElementCollection { #region Methods protected override ConfigurationElement CreateNewElement() { return new ColumnConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { /* * The column's name property (read: not ColumnName) is used to identify this element. */ return ((ColumnConfigurationElement)element).Name; } #endregion } } The beauty of the .NET Configuration system, is that all the underlying mapping is done for you. The ConfigurationCollectionAttribute attribute I have applied here tells the configuration system that it is a collection of type ColumnConfigurationElement, and the add command (used in the config file) should be called "Column", it would default to "add" if this were no present. The ConfigurationElementCollection base class requires us to implement some abstract methods: CreateNewElement - create a new instance of the containing type of the collection. GetElementKey - gets a value that uniquely identifies this instance of the containing type within the collection. Going up the tree, a row contains columns, so we need to create a configuration element for that: namespace ConsoleApplication1 { /// <summary> /// Represents an individual row. /// </summary> public class RowConfigurationElement : ConfigurationElement { #region Constants private const string CFG_COLUMNS = "Columns"; #endregion #region Properties [ConfigurationProperty(CFG_COLUMNS, IsRequired = true, IsDefaultCollection = true)] public ColumnConfigurationElementCollection Columns { get { return (ColumnConfigurationElementCollection)this[CFG_COLUMNS]; } set { this[CFG_COLUMNS] = value; } } #endregion } } We only specify one property here, which is the property that is the collection of columns. We also need a containing collection of rows: namespace ConsoleApplication1 { /// <summary> /// Represents a collection of rows. /// </summary> [ConfigurationCollection(typeof(RowConfigurationElement), AddItemName = "Row")] public class RowConfigurationElementCollection : ConfigurationElementCollection { #region Methods protected override ConfigurationElement CreateNewElement() { return new RowConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { /* * A row doesn't actually have an identifying property, so we will just return a random Guid. */ return Guid.NewGuid(); } #endregion } } I've cheated here, because a row doesn't have any identifying property, we'll just generate a random one, so I've used a guid. Rows are contained in a table, but as this is the root of the tree, we'll use a ConfigurationSection instead of a ConfigurationElement as its base: namespace ConsoleApplication1 { public class TableConfigurationSection : ConfigurationSection { #region Constants private const string CFG_ROWS = "Rows"; #endregion #region Properties [ConfigurationProperty(CFG_ROWS, IsRequired = true, IsDefaultCollection = true)] public RowConfigurationElementCollection Rows { get { return (RowConfigurationElementCollection)this[CFG_ROWS]; } set { this[CFG_ROWS] = value; } } #endregion #region Methods public static TableConfigurationSection GetConfiguration(string name) { return ConfigurationManager.GetSection(name) as TableConfigurationSection; } #endregion } } I added the static method GetConfiguration to allow us to grab the configuration section from the config file. You can then modify the configuration file to support this: <?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="GroupTable" type="ConsoleApplication1.TableConfigurationSection, ConsoleApplication1" /> <section name="ParameterTable" type="ConsoleApplication1.TableConfigurationSection, ConsoleApplication1" /> </configSections> <GroupTable> <Rows> <Row> <Columns> <Column name="Test" columnName ="TEST" value="test value" /> <Column name="Test1" columnName ="TEST1" value="test value1" /> <Column name="Test2" columnName ="TEST2" value="test value2" /> </Columns> </Row> </Rows> </GroupTable> </configuration> You will probably want to read up on custom .NET configuration files for more information. If you want a cleaner xml config, you could override the OnDeserializeUnknownElement which will pass you the element name and an instance of the underlying XmlReader used to read the config. You would need to perform your own element to property mappings though. I've included my sample project for you. For some reason these program wont run for me....? any ideas, i m using vs2005 Link to comment Share on other sites More sharing options...
0 Antaris Veteran Posted February 17, 2009 Veteran Share Posted February 17, 2009 What exception (if any is being thrown). If you want, you can PM me your code and I'll have a look. Link to comment Share on other sites More sharing options...
0 Bookieass Posted February 17, 2009 Author Share Posted February 17, 2009 What exception (if any is being thrown). If you want, you can PM me your code and I'll have a look. attached copy of my solution..... same as yours but in vs2005 gives 4 errors dont knw wat i did wrong??? Thnx in advance ConsoleApplication1.zip Link to comment Share on other sites More sharing options...
0 Antaris Veteran Posted February 17, 2009 Veteran Share Posted February 17, 2009 Sorry for the late reply, but I think I see what you've done: class RowConfigurationElementCollection {/// <summary> /// Represents a collection of rows. /// </summary> [ConfigurationCollection(typeof(RowConfigurationElement), AddItemName = "Row")] public class RowConfigurationElementCollection : ConfigurationElementCollection { #region Methods protected override ConfigurationElement CreateNewElement() { return new RowConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { /* * A row doesn't actually have an identifying property, so we will just return a random Guid. */ return Guid.NewGuid(); } #endregion } } Where you have copied and pasted the code into your VS2005 format project, you have actually pasted the class as an inner class to a class of the same name (say that 10 times while drunk ;)). You need to remove the outer class declaration, so the inner classes are actual child types of the namespace itself: namespace ConsoleApplication1 { /// <summary> /// Represents a collection of rows. /// </summary> [ConfigurationCollection(typeof(RowConfigurationElement), AddItemName = "Row")] public class RowConfigurationElementCollection : ConfigurationElementCollection { #region Methods protected override ConfigurationElement CreateNewElement() { return new RowConfigurationElement(); } protected override object GetElementKey(ConfigurationElement element) { /* * A row doesn't actually have an identifying property, so we will just return a random Guid. */ return Guid.NewGuid(); } #endregion } } Link to comment Share on other sites More sharing options...
Question
Bookieass
Hello, I need a little help
Actually, I want to create a windows based tool that will contain app.config file using Visual Studio 2005
The App.Config file will details regarding
IT will also contain two table
OPC_GROUP
and
PARAMETERS
These tables are present in the Oracle database which we connect too
Now, I want to add some custom information within the App.config file
The custom information holds
Fields, Value;
This values changes frequently
My problem is how can i hold these fields and its correspoinding values in config file??????
and later able to read those information on runtime....... so as to populate the data in the oracle table
Any help would be deeply appreciated
Here is my tryout code
Link to comment
Share on other sites
6 answers to this question
Recommended Posts