Click here to Skip to main content
15,868,236 members
Articles / Programming Languages / Visual Basic
Article

Managing configuration settings persistence in .NET applications

Rate me:
Please Sign up or sign in to vote.
4.32/5 (33 votes)
23 Apr 2004CPOL3 min read 183K   65   37
A simple way to manage config settings read/write persistence through ADO.NET and XML.

Introduction

In the Windows development history, the problem of maintaining the configuration settings for an application has been faced in many ways. For example, in Windows 3.1, the classic approach to the problem was in the use of INI files; more recently a standard way to store config settings was in reading/writing Windows Registry keys. Now, in the .NET age, we can take advantage of the power and simplicity of .config files that I consider a sort of return to the INI approach (simply due to the need of storing config settings near the application's assemblies, to make the XCOPY deployment possible).

Of course, their text-based, simply editable XML structure make .NET configuration files very handy. But, when you use the ConfigurationSettings class (from the System.Configuration namespace) to access them, there are two main limitations:

  • the name for the application configuration file is one and fixed (i.e. web.config or app.exe.config) and
  • the AppSettings property of the ConfigurationSettings class allows only a read-only access to the values stored inside the file.

The simple VB.NET class I propose in this article shows a way to manage configuration settings in a read/write (not read-only) fashion, and to allow multiple configuration files for the same application. The proposed approach is - of course - custom, and it is not related to the classic .NET .config files and their structure, but:

  • the idea of text-based, XML configuration files has been kept;
  • configuration settings continue to be stored as key/value pairs;
  • taking advantage of the ADO.NET DataSet serialization features, this class is implemented in a few lines of code.

The code

VB
Imports System.IO

' Class for managing configuration persistence
Public Class ConfigOpt

  ' This DataSet is used as a memory data
  ' structure to hold config key/value pairs
  ' Inside this DataSet, a single DataTable named ConfigValues is created
  Private Shared DSoptions As DataSet
  ' This is the filename for the DataSet XML serialization
  Private Shared mConfigFileName As String

  ' This property is read-only, because it is set
  ' through Initialize or Store methods
  Public Shared ReadOnly Property ConfigFileName() As String
    Get
      Return mConfigFileName
    End Get
  End Property

  ' This method has to be invoked before using
  ' any other method of ConfigOpt class
  ' ConfigFile parameter is the name of the config file to be read
  ' (if that file doesn't exists, the method
  ' simply initialize the data structure
  ' and the ConfigFileName property)
  Public Shared Sub Initialize(ByVal ConfigFile As String)
    mConfigFileName = ConfigFile
    DSoptions = New DataSet("ConfigOpt")
    If File.Exists(ConfigFile) Then
      ' If the specified config file exists,
      ' it is read to populate the DataSet
      DSoptions.ReadXml(ConfigFile)
    Else
      ' If the specified config file doesn't exists, 
      ' the DataSet is simply initialized (and left empty):
      ' the ConfigValues DataTable is created
      ' with two fields (to hold key/values pairs)
      Dim dt As New DataTable("ConfigValues")
      dt.Columns.Add("OptionName", System.Type.GetType("System.String"))
      dt.Columns.Add("OptionValue", System.Type.GetType("System.String"))
      DSoptions.Tables.Add(dt)
    End If
  End Sub

  ' This method serializes the memory data
  ' structure holding the config parameters
  ' The filename used is the one defined calling Initialize method
  Public Shared Sub Store()
    Store(mConfigFileName)
  End Sub

  ' Same as Store() method, but with the ability
  ' to serialize on a different filename
  Public Shared Sub Store(ByVal ConfigFile As String)
    mConfigFileName = ConfigFile
    DSoptions.WriteXml(ConfigFile)
  End Sub

  ' Read a configuration Value (aka OptionValue),
  ' given its Key (aka OptionName)
  ' If the Key is not defined, an empty string is returned
  Public Shared Function GetOption(ByVal OptionName As String) As String
    Dim dv As DataView = DSoptions.Tables("ConfigValues").DefaultView
    dv.RowFilter = "OptionName='" & OptionName & "'"
    If dv.Count > 0 Then
      Return CStr(dv.Item(0).Item("OptionValue"))
    Else
      Return ""
    End If
  End Function

  ' Write in the memory data structure a Key/Value
  ' pair for a configuration setting
  ' If the Key already exists, the Value is simply updated,
  ' else the Key/Value pair is added
  ' Warning: to update the written Key/Value pair
  ' on the config file, you need to call Store
  Public Shared Sub SetOption(ByVal OptionName _
           As String, ByVal OptionValue As String)
    Dim dv As DataView = DSoptions.Tables("ConfigValues").DefaultView
    dv.RowFilter = "OptionName='" & OptionName & "'"
    If dv.Count > 0 Then
      dv.Item(0).Item("OptionValue") = OptionValue
    Else
      Dim dr As DataRow = DSoptions.Tables("ConfigValues").NewRow()
      dr("OptionName") = OptionName
      dr("OptionValue") = OptionValue
      DSoptions.Tables("ConfigValues").Rows.Add(dr)
    End If
  End Sub

End Class

How to use the code

All the methods the ConfigOpt class exposes are static, so there is no need to create an instance of the class.

Call the Initialize method to read and put in a memory cache an existing config file. You need to call this method also in absence of an existing config file, to initialize the data structure used by ConfigOpt class.

Call the GetOption method to read a configuration value, given its key. Keep in mind that read values are always kept from the cached config key/value pairs (not from the config file directly).

Call the SetOption method to add or update a configuration setting, in the form of a key/value pair. Keys and values are always String types. Keep in mind that addition and updation of config settings are done only in the cached memory structure; to persist all the config key/value pairs on the file system, you need to call the Store method.

Typically, the Store method is called once (when the user closes the application, or he closes a configuration dialog box, or he explicitly wants to save his settings), but you may call this method more often if you need to immediately persist on file the ConfigOpt internal data changes.

An example

Suppose you have, in a Windows Forms application of yours, a configuration form containing some controls (textboxes, checkboxes, etc.); if you need to persist the state of these controls on a file so that their values are maintained between different user sessions, you can use the ConfigOpt class in this way:

VB
Private Sub Form_Load(...) Handles MyBase.Load
  ConfigOpt.Initialize("MyConfig.cfg")
  ReadConfigValues()
End Sub

Private Sub ReadConfigValues()
  txtMyTextbox.Text = ConfigOpt.GetOption("txtMyTextbox")
  chkMyCheckbox.Checked = Boolean.Parse(ConfigOpt.GetOption("chkMyCheckbox"))
  ...
End Sub

Private Sub Form_Closing(...) Handles MyBase.Closing
  WriteConfigValues()
  ConfigOpt.Store()
End Sub

Private Sub WriteconfigValues()
  ConfigOpt.SetOption("txtMyTextbox", txtMyTextbox.Text)
  ConfigOpt.SetOption("chkMyCheckbox", chkMyCheckbox.Checked.ToString())
  ....
End Sub

The generated configuration file will contain this text that you can edit with Notepad whenever you want:

XML
<?xml version="1.0" standalone="yes"?>
<ConfigOpt>
  <ConfigValues>
    <OptionName>txtMyTextbox</OptionName>
    <OptionValue>Sample string typed in txtMyTextbox.</OptionValue>
  </ConfigValues>
  <ConfigValues>
    <OptionName>chkMyCheckbox</OptionName>
    <OptionValue>True</OptionValue>
  </ConfigValues>
  ...
</ConfigOpt>

As suggested by some CodeProject readers (thank you!), you may prefer a more compact XML file with this structure:

XML
<?xml version="1.0" standalone="yes"?>
<ConfigOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ConfigValues OptionName="txtMyTextbox">
     Sample string typed in txtMyTextbox.</ConfigValues>
  <ConfigValues OptionName="chkMyCheckbox">True</ConfigValues>
</ConfigOpt>

In this case, you need to modify the Else branch in the ConfigOpt.Initialize method (where the DataTable is defined), modifying the default XML column mapping as follows:

VB
Dim dt As New DataTable("ConfigValues")
dt.Columns.Add("OptionName", System.Type.GetType("System.String"))
dt.Columns.Add("OptionValue", System.Type.GetType("System.String"))
dt.Columns("OptionName").ColumnMapping = MappingType.Attribute
dt.Columns("OptionValue").ColumnMapping = MappingType.SimpleContent
DSoptions.Tables.Add(dt)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
Italy Italy
I was born in 1970.

My first computer experience dates back to early 80s, with a Sinclair ZX81.
From that time on, as many "friends" say, my IT-illness has increased year by year.

I graduated in Electronic Engineering and earned the following Microsoft certifications:
MCP, MCT, MCDBA, MCSD, MCAD, MCSD for .NET (early achiever).

I worked in IT as a developer, a teacher, a consultant, a technical writer, a technical leader.
IT knowledge applied to real life is my primary interest and focus.

Comments and Discussions

 
GeneralCCNet XmlConfig Plugin Pin
void leenux();16-Apr-11 7:12
void leenux();16-Apr-11 7:12 
GeneralThanx Pin
Johannekie3-Sep-08 0:37
Johannekie3-Sep-08 0:37 
GeneralThanx! Pin
Dennis Betten9-Apr-08 5:49
Dennis Betten9-Apr-08 5:49 
QuestionHow can I update the memory cache with application's data configuration? Pin
MaOrellana10-Dec-07 4:56
MaOrellana10-Dec-07 4:56 
QuestionHow can I update the memory cache with application's data configuration? Pin
MaOrellana10-Dec-07 4:55
MaOrellana10-Dec-07 4:55 
GeneralMultiple Instances Pin
Mackerel Catcher25-Aug-06 6:46
Mackerel Catcher25-Aug-06 6:46 
GeneralRe: Multiple Instances Pin
Alberto Venditti3-Sep-06 4:35
Alberto Venditti3-Sep-06 4:35 
GeneralAnother C# rewrite with more functionality Pin
wiyosaya11-May-06 3:36
wiyosaya11-May-06 3:36 
Generalrewriting the code for c# programmers Pin
the termin8or2-Apr-06 9:05
the termin8or2-Apr-06 9:05 
GeneralAdd this to your ConfigOpt.vb Class to encrypt your config file Pin
Tinus Groenewald7-Nov-05 3:15
Tinus Groenewald7-Nov-05 3:15 
GeneralMultiple Sections/Nodes Pin
amnonevo17-Oct-05 12:09
amnonevo17-Oct-05 12:09 
GeneralRe: Multiple Sections/Nodes Pin
Anonymous18-Oct-05 3:42
Anonymous18-Oct-05 3:42 
Question[Message Deleted] Pin
amnonevo18-Oct-05 5:24
amnonevo18-Oct-05 5:24 
AnswerRe: Multiple Sections/Nodes Pin
Alberto Venditti19-Oct-05 21:42
Alberto Venditti19-Oct-05 21:42 
GeneralRe: Multiple Sections/Nodes Pin
amnonevo20-Oct-05 11:31
amnonevo20-Oct-05 11:31 
GeneralUsing standard .NET configuration schema Pin
Member 1217646810-Aug-05 4:31
Member 1217646810-Aug-05 4:31 
GeneralRe: Using standard .NET configuration schema Pin
Alberto Venditti10-Aug-05 7:44
Alberto Venditti10-Aug-05 7:44 
GeneralRe: Using standard .NET configuration schema Pin
VlastaH15-Oct-05 12:01
VlastaH15-Oct-05 12:01 
QuestionMay have found a problem? Pin
DavidMT7-Feb-05 16:53
DavidMT7-Feb-05 16:53 
AnswerRe: May have found a problem? Pin
DavidMT7-Feb-05 17:04
DavidMT7-Feb-05 17:04 
AnswerRe: May have found a problem? Pin
Alberto Venditti7-Feb-05 21:05
Alberto Venditti7-Feb-05 21:05 
GeneralRe: May have found a problem? Pin
Luca Crisi, MCP26-Oct-05 18:57
Luca Crisi, MCP26-Oct-05 18:57 
GeneralRe: May have found a problem? Pin
Alberto Venditti27-Oct-05 1:57
Alberto Venditti27-Oct-05 1:57 
GeneralRe: May have found a problem? Pin
Luca Crisi, MCP27-Oct-05 5:58
Luca Crisi, MCP27-Oct-05 5:58 
QuestionIsolated Storage? Pin
Member 16367939-Jan-05 20:48
Member 16367939-Jan-05 20:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.