I am struggling with how to persist preferences/settings/configurations that are read but also updated by my C# application. My configurations can be
individual ints, strings, byte[] that represent connection strings, directory names, file names,...
collections of strings or other value types.
class object instances that represent a group of mostly value types.
-> Such settings are accessed in different, sometimes unrelated classes.
I am currently pondering what you think is best practice, given the following bullet points:
A self-written key/value store. Internally the key/values are stored in a hashtable and the hashtable is serialized/deserialized for persistence.
Entity Framework: I have access to the MS entity framework and run MySQL server instances.
Text file / XML file
Any other/better ideas?
Exclusion:
I do not want to store any settings in Settings.settings, App.config, or the like
I do not want to use the registry
I do not want to store settings in any obscure roaming directory structures or other hidden directories. The settings should either be stored in a dedicated database/table or in the application executable folder or sub-folder.
Questions:
I am not sure whether to store all configuration objects in one and the same entity or whether I should setup several such entities to store groups of configurations?
what is the best way to persist such lightweight objects that function as settings/configuration and later load and access those?
You can store your settings in WMI namespaces. We had stored one of our product specific settings and configuration there. Also though you have excluded App.config, Application specific settings would be normally stored therein.
I would suggest using XML for this type of scenario.
It's easy to write and read
Human readable, and easy to open and edit manually
With LINQ to XML you can query for specific data and convert that data into strongly typed objects
Widely used and understood, especially for config files
Flexible structure
These are just a few things that come to mind. Here is some example code of querying the file for all protocols of type tcp.
XElement settings = XElement.Load("settings.xml");
IEnumerable<XElement> tcpSettings = settings.Elements("protocol").Where(o => o.Attribute("name").Value == "tcp")
// make some changes to the settings
settings.Save("settings.xml");
Edit:
Serialize Class containing Dictionary member
Related
I have a C# application which is used to modify PowerPoint files. The files are in our network and a lot of people need to work with them. But at every given time, only one person works with a presentation.
I used to store some metadata, for each presentation, in a central serialized xml file located in our network. The struture of the metadata is a simple List where each item is a filename and other properties. The filename is used to identify each entry.
Now my program is used often used by different people, who are working on different presentations and when they go home, my program saves the metadata to the file. Unfortunately, the last user to go home wins and overwrites all changes by other users.
So how can I avoid that? Clearly, I need a better data storage technique, which saves only the changes made by the user. But I cannot use any other technique than files stored on our network (but I am not limited to xml files...)
Why not use a SQLite database? It stores all it's data in a single file (which you can store on your network), and gives you the flexibility of a relational database where you can use techniques like pessimistic and/or optimistic concurrency checks. You'll also be able to more easily store each user's data.
EDIT: An SO question which deals with how to use SQLite from c# applications
I have some global settings
For example some below are
ShortLeaveAllowedInOneDay = 2
LeaveAllowedInMonth = 3
I have following options to store these global settings
1-Store in Database table
2-Store in Webconfig file
3-Store in class as const filed
4-In XML file
Could you please suggest me which one is better approach and why
I am using Asp.net MVC3
with sqlserver 2005
It depends on your requirements, each one of these options has it own advantages and disadvantages. It tried to list a few:
1. Store in Database table
Advantages:
Relatively easy to read settings.
Possible to write/update settings.
Access is to the database is fast.
Updates to database values are immediately available.
DB is can be shared across multiple instances in clustered environment.
Disadvantages:
More infrastructure required than the rest of the options (i.e. tables, db access etc).
If done incorrectly DB IO can become an issue. (Can be solved with caching strategies)
2. Store in web.config file
Advantages:
Simple to add and access settings.
Disadvantages:
Changes to the web.config may result in the application pool to restart.
Settings are generally not encrypted.
In a clustered environment the file has to be kept in sync with other instances.
Generally have to deal with strings data types and possible invalid user input when settings are set.
3. Store in class as const field
Advantages:
Very simple to work with.
Can work with static types.
Good first step towards refactoring settings into one of the other options.
Disadvantages:
Requires rebuild for settings to change.
4. In XML file
Advantages:
Convenient for storing complex settings such a hierarchies.
Custom XML config settings can be embedded inside the web.config. (Popular option see log4net as one such example)
Updates to the config files can be made without restarting the application pool.
An XSD can enforce the validity of the settings in the file (both structure and data types)
Disadvantages:
It is XML. Not really human readable, formats like YAML improves on that.
Implementation required to parse XML for reading and writing settings.
If you need them to be configured by a user of your software I would not do option 3. If they are settings that you define as a programmer and do not expect them to be changed when your application is in production you could do that.
I would say that option 4 and 2 are basically the same, conceptually, and it is personal preference which to choose. Personally I like to define a custom configuration section and then have just that section defined in it's own .config file (this shows how to do that) so that you don't have a really massive web.config that the user has to navigate.
I would choose option 1 if I had a scenario where I had multiple components that all need access to the same configuration. If all you are building is a single web application, it does not feel necessary to me to do that but if, for example, you have a web application and some other client application and both require access to the database then storing the configuration there is a good choice.
Add an AppSettings session in the web config file, that can be accessed from the code directly like :
System.Configuration.ConfigurationManager.AppSettings["ShortLeaveAllowedInOneDay "];
EDIT :
and the Confir file would look like :
<appSettings>
<add key="ShortLeaveAllowedInOneDay " value="2" />
</appSettings>
No approach is inherently better than the others.
The best approach depends entirely on what your requirements are for things like security, scalability, flexibility, read-only vs. writeable, config complexity, and so on.
Storing global variables in the web.config file is a very common task.
Storing values in your web.config file is extremely useful when a database might be overkill and when you don't need a separate external file.
Reading the .xml file several times for each page lifecycle would be VERY bad for performance.
I would definitely go for web.config.
You can store the variable in Web.config file.
I will be more practical. Two basic cases.
Values/parameters that changes ones and are critical to start/run/initialize the program
Values are change offend, or they are different for every user.
You store the initial variables on web.config, and all the other on database. If you do not have database, then what ever is available, like XML file.
I wrote a reminder program that runs automatically on startup. I want to know if there is a way, other than SQL-Server, to store event, date and time data. I do not want to use SQL-Server for this work, because I think SQL-Server is very big for this simple task. I think that I can use a file to store data in it. What do you think about this?
Some common ways to store information:
As a file. You have many options where you can store the file. For instance, user directory, and program directory. Further explanation here and here. I prefer using a serializer (xml or json).
As a registry entry. You store your information as key-value pairs.
In a light-weight database:
RavenDB: its document-oriented, and stores data in json format
SQLite: relational; I recommend this SQLite Admin for managing purpose
Registry entries are more safe regarding user actions. On the other hand, files can be easily deleted.
You always have the option, to encrypt your information.
As a side note, you can also use PostSharp to declare variables to be stored in your registry. The code becomes something like this:
[RegistryBacking]
private bool _boolean;
I can provide code later if you need it... when I'm home again.
For the part where to persist
From this document (Managing User Data Deployment Guide, download):
Windows uses the Local and LocalLow folders for application data
that does not roam with the user. Usually this data is either machine
specific or too large to roam.
Windows uses the Roaming folder for application specific data, such
as custom dictionaries, which are machine independent and should roam
with the user profile.
So, I suggest using AppData\Roaming and persisting to a file since I consider a 'reminder app' to be user specific. And domain users for example would consider that valuable (syncing to server).
Local and LocalLow (the latter is used for low integrity mode, for applications with reduced privileges) would be more appropriate for some machine/installation specific data which can be calculated on-the-fly.
Registry seems great for some low amount of keys, but doesn't seem to be the best option for such use.
There is another option - IsolatedStorage, which should be used when mentioned options are not applicable, like when using ClickOnce deployments.
For the part how to persist your data to a file ... well, pick your favorite. You could use SQLite database which comes really lightweigt if you want more control and power or just use XML serialization to a file if you consider using SQLite an overkill. Or any of other viable options.
XML. .NET has classes that makes handling xml files easy. If you're saving structured data then XML might be your best bet.
I have for very similar reasons tried some easy to deploy databases and yet use the knowledge i have.
VistaDB 3.x and 4 are my first choice because they are very much SQL Server compaible and allows me to switch to sql server anytime i like. This supports EF too!!!
Next is db4o by Versant which is very very handy. I use it mostly for quick prototyping but i have deployed to several small solutions and perfect for your kind of application.
I hope that helps!
I am currently writing an IRC client and I've been trying to figure out a good way to store the server settings. Basically a big list of networks and their servers as most IRC clients have.
I had decided on using SQLite but then I wanted to make the list freely available online in XML format (and perhaps definitive), for other IRC apps to use. So now I may just store the settings locally in the same format.
I have very little experience with either ADO.NET or XML so I'm not sure how they would compare in a situation like this.
Is one easier to work with programmatically? Is one faster? Does it matter?
It's a vaguer question than you realize. "Settings" can encompass an awful lot of things.
There's a good .NET infrastructure for handling application settings in configuration files. These, generally, are exposed to your program as properties of a global Settings object; the classes in the System.Configuration namespace take care of reading and persisting them, and there are tools built into Visual Studio to auto-generate the code for dealing with them. One of the data types that this infrastructure supports is StringCollection, so you could use that to store a list of servers.
But for a large list of servers, this wouldn't be my first choice, for a couple of reasons. I'd expect that the elements in your list are actually tuples (e.g. host name, port, description), not simple strings, in which case you'll end up having to format and parse the data to get it into a StringCollection, and that is generally a sign that you should be doing something else. Also, application settings are read-only (under Vista, at least), and while you can give a setting user scope to make it persistable, that leads you down a path that you probably want to understand before committing to.
So, another thing I'd consider: Is your list of servers simply a list, or do you have an internal object model representing it? In the latter case, I might consider using XML serialization to store and retrieve the objects. (The only thing I'd keep in the application configuration file would be the path to the serialized object file.) I'd do this because serializing and deserializing simple objects into XML is really easy; you don't have to be concerned with designing and testing a proper serialization format because the tools do it for you.
The primary reason I look at using a database is if my program performs a bunch of operations whose results need to be atomic and durable, or if for some reason I don't want all of my data in memory at once. If every time X happens, I want a permanent record of it, that's leading me in the direction of using a database. You don't want to use XML serialization for something like that, generally, because you can't realistically serialize just one object if you're saving all of your objects to a single physical file. (Though it's certainly not crazy to simply serialize your whole object model to save one change. In fact, that's exactly what my company's product does, and it points to another circumstance in which I wouldn't use a database: if the data's schema is changing frequently.)
I would personally use XML for settings - .NET is already built to do this and as such has many built-in facilities for storing your settings in XML configuration files.
If you want to use a custom schema (be it XML or DB) for storing settings then I would say that either XML or SQLite will work just as well since you ought to be using a decent API around the data store.
Every tool has its own right
There is plenty of hype arround XML, I know. But you should see, that XML is basically an exchange format -- not a storage format (unless you use a native XML-Database that gives you more options -- but also might add some headaches).
When your configuration is rather small (say less than 10.000 records), you might use XML and be fine. You will load the whole thing into your memory and access the entries there. Done.
But when your configuration is so big, that you dont want to load it completely, than you rethink your decission and stay with SQLite which gives you the option to dynamically load those parts of the configuration you need.
You could also provide a little tool to create a XML file from the DB-content -- creation of XML from a DB is a rather simple task.
Looks like you have two separate applications here: a web server and a desktop client (because that is traditionally where these things run), each with its own storage needs.
On the server side: go with a relational data store, not Xml. Basically at some point you need to keep user data separate from other user data on the server. XML is not a good store for that.
On the client: it doesn't really matter. Xml will probably be easier for you to manipulate. And don't think that because you are using one technology in one setting, you have to use it in the other.
Pardon my ignorance, but I've never really developed Windows applications. How do you store user settings? Is an embedded database the preferred method?
I think you are looking for user settings:
The .NET Framework 2.0 allows you to
create and access values that are
persisted between application
execution sessions. These values are
called settings. Settings can
represent user preferences, or
valuable information the application
needs to use. For example, you might
create a series of settings that store
user preferences for the color scheme
of an application. Or you might store
the connection string that specifies a
database that your application uses.
Settings allow you to both persist
information that is critical to the
application outside of the code, and
to create profiles that store the
preferences of individual users.
It depends on what kind of settings. There are a variety of methods from embedded databases (like SQLite) to XML files, to the Registry.
If the settings are very few, the registry often makes sense.
If the settings are more complicated, and need to be hand edited, you can use XML files or JSON.
If the settings are complex and do not need hand editing, an embedded database like SQLite, .NetBtree, or BerkelyDB .NET are good choices.
Use Blane's Pegasus Library (http://pegasus.codeplex.com/).
You could use his XmlSerializationHelper class which makes it a snap to turn objects into XML and vice versa.
Or you could use Isolated Storage (I would provide a link to MSDN if I wasn't a new user and restricted to one hyperlink per post). If you use IsolatedStorage, consider using Blane's IsolatedStorageHashtable class.
It all depends on what size of an application you are building. If you are on something simple, let's say, "family shopping list", you can store the settings in a good old plain text file.
If you are building something bigger, for example a "classmate notifier" you can use an XML file, or some kind of other resource.
For any bigger application you should use some kind of relational database, for storing user data.