C# .NET - method to store some very small scale persistent information?
Asked Answered
M

7

27

I have an application that will need extremely little persistent storage. Realistically, we're talking about < 30 integers. All the application needs is to know those integers on next startup (and the integers do change as it runs).

A database is overkill for this, but I don't particularly want to just use a text file either.

Does C# have any mechanism for persisting small values like this between runs? I've noticed you can store things in resource files and some other places - I don't know if you can change those in the runtime though. I'm just learning C# & .NET for a new job, so apologies if this is a silly question!

Mendelism answered 25/4, 2012 at 21:3 Comment(3)
staright-up console app which will probably change into a windows service eventually once I figure out what I'm doing.Mendelism
I would then go for the File Storing using an XML file as .NET is great or writing and reading from it, plus you can even use Linq2Xml...Ruhnke
Can't believe how many answers I got for this :) Thanks everyone, was good to have the range of options.Mendelism
B
28

Here is a blurp of another SO post that explains how to setup Application Settings, this is a simple file based solution for reading/writing values.

"If you work with Visual Studio then it is pretty easy to get persistable settings. Right click on the project in Solution Explorer, choose Properties. Select the Settings tab, click on the hyperlink if settings doesn't exist. Use the Settings tab to create application settings. Visual Studio creates the files Settings.settings and Settings.Designer.settings that contain the singleton class Settings inherited from ApplicationSettingsBase. You can access this class from your code to read/write application settings:"

Settings.Default["SomeProperty"] = "Some Value";
Settings.Default.Save(); // Saves settings in application configuration file
Boarer answered 25/4, 2012 at 21:14 Comment(1)
Application Scope Settings are read-only on runtime, User Scope settings are read-write but they will be erased for each process that he runs - see my answer: https://mcmap.net/q/534320/-saving-setting-to-a-exe/…Ruhnke
K
6

I would use embeeded sqlite database.

http://www.codeproject.com/Articles/22165/Using-SQLite-in-your-C-Application

SQLite is a small, fast and embeddable database where the database engine and the interface are combined into a single library. It also has the ability to store all the data in a single file. So if your application requires a standalone database, SQLite is perhaps the perfect choice for you. There are, of course, other reasons for choosing SQLite including:

SQLite has a small memory footprint and only a single library is required to access databases, making it ideal for embedded database applications. SQLite has been ported to many platforms and runs even on Windows CE and Palm OS. SQLite is ACID-compliant, meeting all four criteria - Atomicity, Consistency, Isolation, and Durability. SQLite implements a large subset of the ANSI-92 SQL standard, including views, sub-queries and triggers. No problem of extra database drivers, ODBC configuration required. Just include the library and the data file with your application. SQLite has native language APIs for C/C++, PHP, Perl, Python, Tcl etc. Native API for C# is still not present.

Kazak answered 25/4, 2012 at 21:6 Comment(2)
+1 for the good answer - I appreciate the detail. I'm actually quite familiar with SQLite and like it - but it requires me to get a big API and include lots of code for the sake of storing a few integers in an app significantly smaller than the SQLite interface, so it's probably overkill too :( Thank you for the help though :)Mendelism
For just 30 integers,why don't use use app.config? It seems more logical to me now?Kazak
E
6

You could just serialize the list to an xml file. This is how you save it:

var xs = new System.Xml.Serialization.XmlSerializer(typeof(List<int>));
List<int> ints = new List<int> { 1, 2, 3 };

using (FileStream fs = new FileStream(@"C:\store.xml", FileMode.OpenOrCreate))
{
    xs.Serialize(fs, ints); 
}

And retrieving it is equally easy:

using (FileStream fs = new FileStream(@"C:\store.xml", FileMode.OpenOrCreate))
{
    ints = xs.Deserialize(fs) as List<int>;
}
Erato answered 25/4, 2012 at 21:11 Comment(1)
for future improvements it would be better to serialise class with List<int> as one of fieldVersatile
M
4

If you're using c# 4.0 and upwards, you might want to have a look at the new Memory Mapped Files.

Using Persisted Memory Mapped files will give you the ease of a file, but the speed of being mapped into memory. You would of course still have to manage the file format yourself.

  • Persisted memory-mapped files

Persisted files are memory-mapped files that are associated with a source file on a disk. When the last process has finished working with the file, the data is saved to the source file on the disk. These memory-mapped files are suitable for working with extremely large source files.

This probably may be overkill for 30 integers, but it's another option, especially if speed is key.

Moonfish answered 25/4, 2012 at 21:29 Comment(0)
R
3

I would choose file storage and avoid database or registry as the first it needs to much of the framework and the second ... ohh well, never play with Registry :)

using XML as a file storage this is a great read:

How does one parse XML files?

you can create your file to save all ID's in the same node, or write one ID per node, it's up to you, something like this would be fine:

<?xml version="1.0" encoding="utf-8" ?> 
<settings>
    <selected>
        <id>1</id>
        <id>8</id>
        <id>12</id>
        <id>15</id>
    </selected>
</settings>

In order to create such file:

  XmlDocument doc = new XmlDocument();
  XmlElement set = (XmlElement)doc.AppendChild(doc.CreateElement("settings"));
  XmlElement sel = (XmlElement)set.AppendChild(doc.CreateElement("selected"));

  int[] selectedIds = new int[] { 1, 2, 3, 4, 5 };

  foreach (int id in selectedIds)
     sel.AppendChild(doc.CreateElement("id")).InnerText = id.ToString();

  string path = Path.GetDirectoryName(Application.ExecutablePath);
  doc.Save(path + "/settings.xml");

In order to read you can use XmlReader, XmlTextReader, XDocument, etc...

Ruhnke answered 25/4, 2012 at 21:14 Comment(1)
This is actually much easier and cleaner to do using the Xml Attributes such as XmlRootAttribute, XmlElementAttribute and XmlAttributeAttribute. Simply declare a class to represent your XML file, annotate it with the proper attributes, and use the XmlSerializer class to serialize/deserialze in a single line.There's not really a lot of reasons to mess around with manually modifying an XmlDocument.Ossiferous
H
0

You can use IMemoryCache and AcroFS library as an additional layer for persistence!

All you need is calling .Persistent() method to obtain the persistent instance of the memory cache.

_memoryCache
   .Persistent()
   .Set(key, value, TimeSpan.FromMinutes(1));

If you don't need to cache you can simply use AcroFS without IMemoryCache :

var _repository = FileStore.CreateStore();

// store the model with a custpm key
_repository.Store("my-model", MyModel);

// load model
var model = _repository.Load<MyModel>("my-model");

Horseshoes answered 11/2, 2022 at 11:18 Comment(0)
R
0

I've long been amused by this question, which originally didn't mention the "just use a file" possibility, but seemed purposefully constructed to have us yelling "just use a file!" at our monitors.

I have to make a living in this field, so I tend to bite my tongue at this sort of quasi-architectural pearl-clutching. Some of the top answers are just so wrong-headed, though, that I can remain silent no more.

Settings.settings is an architectural boondoggle that is conspicuously absent from any real, production .NET code I've ever seen (and I've seen a lot). In particular it breaks down with respect to application version number changes. Yeah, there's a workaround, but you have to pick through a lot of OO detritus to get there.

SQLite... where do I even start? Who looks at an even halfway-modern codebase, needs to do what OP is asking about, and thinks, "you know, what would really help here is to inject an entire relational database written in C, twenty years ago, right here into my own thread"?

The right answer here is to do what Settings.settings does (i.e. put a file into the folder where Windows wants you to put application files) without using Settings.settings.

Risibility answered 1/4, 2022 at 14:3 Comment(2)
You come along as a little passive-aggressive, nevertheless, I agree with what you said so I voted you up.Exposure
@HeythamAlShayeb My tone here was less than perfect, I admit. There's a certain mentality that "if it's more work, it must be better" that's taken hold in the industry, and it does frustrate me. Computers should be less work, or they don't make sense. Rolodexes, calendars, long division, log tables... computers were supposed to save us labor over these things. People lose sight of that IMO.Risibility

© 2022 - 2024 — McMap. All rights reserved.