Beste Möglichkeit, Daten lokal in .NET (C #) zu speichern

74

Ich schreibe eine Anwendung, die Benutzerdaten aufnimmt und lokal zur späteren Verwendung speichert. Die Anwendung wird ziemlich oft gestartet und gestoppt, und ich möchte, dass die Daten beim Start / Ende der Anwendung gespeichert / geladen werden.

Es wäre ziemlich einfach, wenn ich flache Dateien verwenden würde, da die Daten nicht wirklich gesichert werden müssen (sie werden nur auf diesem PC gespeichert). Die Optionen, die ich glaube, sind also:

  • Flat Files
  • XML
  • SQL DB

Die Pflege von Flatfiles erfordert etwas mehr Aufwand (keine integrierten Klassen wie bei XML), ich habe jedoch noch kein XML verwendet, und SQL scheint für diese relativ einfache Aufgabe ein Overkill zu sein.

Gibt es noch andere Möglichkeiten, die es wert sind, erkundet zu werden? Wenn nicht, welche davon ist die beste Lösung?


Bearbeiten: Um dem Problem ein wenig mehr Daten hinzuzufügen, möchte ich im Grunde nur ein Wörterbuch speichern, das so aussieht

Dictionary<string, List<Account>> 

Dabei ist Konto ein anderer benutzerdefinierter Typ.

Würde ich das Diktat als XML-Wurzel und dann den Kontotyp als Attribute serialisieren?


Update 2:

So ist es möglich, ein Wörterbuch zu serialisieren. Was es kompliziert macht, ist, dass der Wert für dieses Diktat selbst ein Generikum ist, bei dem es sich um eine Liste komplexer Datenstrukturen vom Typ Konto handelt. Jedes Konto ist ziemlich einfach, es sind nur eine Reihe von Eigenschaften.

Nach meinem Verständnis besteht das Ziel hier darin, Folgendes zu erreichen:

<Username1>
    <Account1>
        <Data1>data1</Data1>
        <Data2>data2</Data2>
    </Account1>
</Username1>
<Username2>
    <Account1>
        <Data1>data1</Data1>
        <Data2>data2</Data2>
    </Account1>
    <Account2>
        <Data1>data1</Data1>
        <Data2>data2</Data2>
    </Account2>
 </Username2>

Wie Sie sehen können, ist die Erbschaft

  • Benutzername (Zeichenfolge)>
  • Konto (jedes Konto in der Liste)>
  • Kontodaten (dh Klasseneigenschaften).

Dieses Layout von a zu erhalten, Dictionary<Username, List<Account>>ist das Knifflige und das Wesentliche dieser Frage.

Hier gibt es viele Anleitungen zur Serialisierung, was meine Schuld ist, da ich es nicht frühzeitig klarer gemacht habe, aber jetzt suche ich nach einer definitiven Lösung.

George
quelle
Geben Sie mehr Details über die Art der Anwendung und die gespeicherten Daten, auch die erwartete Größe
AK_
3
Zum Serialisieren eines Wörterbuchs: stackoverflow.com/questions/1111724
Cheeso

Antworten:

26

Ich würde die Datei als JSON speichern . Da Sie ein Wörterbuch speichern, das nur eine Name / Wert-Paarliste ist, ist dies ziemlich genau das, wofür json entwickelt wurde.
Es gibt einige anständige, kostenlose .NET json-Bibliotheken - hier ist eine, aber eine vollständige Liste finden Sie unter dem ersten Link.

Zebrabox
quelle
json ist etwas ungewöhnlich für die lokale Speicherung, aber es ist definitiv eine großartige Lösung. Besonders mit einer Bibliothek wie Newtonsofts Json.NET
AFract
2
Anstatt mich auf eine Bibliothek eines Drittanbieters zu verlassen, würde ich die Daten unter Verwendung des eingebauten Dataset-Typs speichern, der sehr einfach auf die Festplatte zu schreiben ist (siehe Tom Millers Beispiel unten)
EKanadily
24

Es hängt wirklich davon ab, was Sie speichern. Wenn Sie über strukturierte Daten sprechen, eignet sich entweder XML oder ein sehr leichtes SQL-RDBMS wie SQLite oder SQL Server Compact Edition gut für Sie. Die SQL-Lösung wird besonders überzeugend, wenn die Daten eine triviale Größe überschreiten.

Wenn Sie große Teile relativ unstrukturierter Daten speichern (z. B. binäre Objekte wie Bilder), sind natürlich weder eine Datenbank noch eine XML-Lösung geeignet, aber angesichts Ihrer Frage schätze ich, dass es sich eher um die erstere als um die letztere handelt.

Adam Robinson
quelle
XML-Konfigurationsdateien müssen strukturiert sein?
@Roboto: XML ist per Definition strukturiert. Das bedeutet jedoch nicht, dass Sie sie stark strukturiert verwenden müssen.
Adam Robinson
17

Alle oben genannten sind gute Antworten und lösen im Allgemeinen das Problem.

Wenn Sie eine einfache und kostenlose Möglichkeit zur Skalierung auf Millionen von Daten benötigen, probieren Sie das ESENT Managed Interface-Projekt auf GitHub oder in NuGet aus .

ESENT ist eine einbettbare Datenbankspeicher-Engine (ISAM), die Teil von Windows ist. Es bietet zuverlässige, abgewickelte, gleichzeitige und leistungsstarke Datenspeicherung mit Sperren auf Zeilenebene, Write-Ahead-Protokollierung und Snapshot-Isolation. Dies ist ein verwalteter Wrapper für die ESENT Win32-API.

Es hat ein PersistentDictionary-Objekt, das recht einfach zu verwenden ist. Stellen Sie sich das als Dictionary () - Objekt vor, aber es wird automatisch von der Festplatte geladen und ohne zusätzlichen Code auf der Festplatte gespeichert.

Zum Beispiel:

/// <summary>
/// Ask the user for their first name and see if we remember 
/// their last name.
/// </summary>
public static void Main()
{
    PersistentDictionary<string, string> dictionary = new PersistentDictionary<string, string>("Names");
    Console.WriteLine("What is your first name?");
    string firstName = Console.ReadLine();
    if (dictionary.ContainsKey(firstName))
    {
        Console.WriteLine("Welcome back {0} {1}", firstName, dictionary[firstName]);
    }
    else
    {
        Console.WriteLine("I don't know you, {0}. What is your last name?", firstName);
        dictionary[firstName] = Console.ReadLine();
    }

Um Georges Frage zu beantworten:

Unterstützte Schlüsseltypen

Nur diese Typen werden als Wörterbuchschlüssel unterstützt:

Boolesches Byte Int16 UInt16 Int32 UInt32 Int64 UInt64 Float Double Guid DateTime TimeSpan String

Unterstützte Werttypen

Wörterbuchwerte können beliebige Schlüsseltypen, nullfähige Versionen der Schlüsseltypen, Uri, IPAddress oder eine serialisierbare Struktur sein. Eine Struktur gilt nur dann als serialisierbar, wenn sie alle folgenden Kriterien erfüllt:

• Die Struktur ist als serialisierbar markiert. • Jedes Mitglied der Struktur ist entweder: 1. Ein primitiver Datentyp (z. B. Int32) 2. Ein String, Uri oder IPAddress 3. Eine serialisierbare Struktur.

Oder anders ausgedrückt: Eine serialisierbare Struktur darf keine Verweise auf ein Klassenobjekt enthalten. Dies geschieht, um die API-Konsistenz zu erhalten. Durch Hinzufügen eines Objekts zu einem PersistentDictionary wird durch Serialisierung eine Kopie des Objekts erstellt. Durch Ändern des Originalobjekts wird die Kopie nicht geändert, was zu verwirrendem Verhalten führen würde. Um diese Probleme zu vermeiden, akzeptiert das PersistentDictionary nur Werttypen als Werte.

Kann serialisiert werden [Serializable] struct Good {public DateTime? Empfangen; öffentlicher String Name; öffentlicher Dezimalpreis; öffentliche Uri Url; }}

Kann nicht serialisiert werden [Serializable] struct Bad {public byte [] Data; // Arrays werden nicht unterstützt public Exception Error; // Referenzobjekt}

GalacticJello
quelle
Diese Methode ersetzt im Grunde das eingebaute Generikum durch ein beständiges Wörterbuch. Es ist eine ziemlich elegante Lösung, aber wie geht es mit komplexen Objekten um, wie im OP-Beispiel? Speichert es alles im Diktat oder nur das Diktat selbst?
George
Dies könnte das letztendliche Ziel, die Listen vom Typ Konto zu speichern, verfehlen. Die Schlüssel wären in Ordnung, aber es könnte schwierig sein, das Generikum serialisierbar zu machen: /.
George
1
Alle anderen, die dies implementieren, können davon profitieren, dass Sie Nuget verwenden können, um ManagedEsent abzurufen. Dann müssen Sie auf Esent.Collections.DLL und Esent.ISAM.DLL verweisen. Fügen Sie dann "using Microsoft.Isam.Esent.Collections.Generic;" hinzu. um den PersistentDictionary-Typ abzurufen. Die Sammlungs-DLL muss möglicherweise von der Download-Option auf manageesent.codeplex.com
Steve Hibbert
Aus "ManagedEsent" wurde "Microsoft.Database.ManagedEsent". Sie sollten stattdessen "Microsoft.Database.Collections.Generic" von nuget verwenden, da es sowohl ManagedEsent als auch ISAM enthält.
VoteCoffee
14

XML ist über die Serialisierung einfach zu verwenden. Verwenden Sie isolierten Speicher .

Siehe auch So entscheiden Sie, wo der Status pro Benutzer gespeichert werden soll. Registrierung? Anwendungsdaten? Isolierte Lagerung?

public class UserDB 
{
    // actual data to be preserved for each user
    public int A; 
    public string Z; 

    // metadata        
    public DateTime LastSaved;
    public int eon;

    private string dbpath; 

    public static UserDB Load(string path)
    {
        UserDB udb;
        try
        {
            System.Xml.Serialization.XmlSerializer s=new System.Xml.Serialization.XmlSerializer(typeof(UserDB));
            using(System.IO.StreamReader reader= System.IO.File.OpenText(path))
            {
                udb= (UserDB) s.Deserialize(reader);
            }
        }
        catch
        {
            udb= new UserDB();
        }
        udb.dbpath= path; 

        return udb;
    }


    public void Save()
    {
        LastSaved= System.DateTime.Now;
        eon++;
        var s= new System.Xml.Serialization.XmlSerializer(typeof(UserDB));
        var ns= new System.Xml.Serialization.XmlSerializerNamespaces();
        ns.Add( "", "");
        System.IO.StreamWriter writer= System.IO.File.CreateText(dbpath);
        s.Serialize(writer, this, ns);
        writer.Close();
    }
}
Cheeso
quelle
1
Dies ist weder sehr portabel noch ordentlich
3
Es sieht aus wie Code zum Ausschneiden und Einfügen, sodass Sie das erste Poster sein können. Wäre besser gewesen, einfach bei deinen Links zu bleiben.
8
Nun ja, ich habe es direkt aus der App herausgeschnitten, die ich geschrieben habe, das macht das. Roboto, was ist dein Problem?
Cheeso
Es wird nicht einmal Dependency Injection verwendet! Hast du das Memo nicht bekommen?
Steve Smith
Ich stimme der XML-Empfehlung zu, aber nachdem ich es selbst ausprobiert habe, stoße ich auf eine Einschränkung des isolierten Speichers - es werden unterschiedliche Dateien erstellt, je nachdem von welcher Assembly der Code ausgeführt wird. Endete nur mit AppData \ Roaming viaPath.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"{AppName}\{FileName}.XML");
Ory Zaidenvorm
9

Ich empfehle die XML-Lese- / Schreibklasse für Dateien, da sie leicht serialisiert werden kann.

Serialisierung in C #

Die Serialisierung (in Python als Beizen bezeichnet) ist eine einfache Möglichkeit, ein Objekt in eine binäre Darstellung umzuwandeln, die dann z. B. auf die Festplatte geschrieben oder über eine Leitung gesendet werden kann.

Dies ist beispielsweise zum einfachen Speichern von Einstellungen in einer Datei nützlich.

Sie können Ihre eigenen Klassen serialisieren, wenn Sie sie mit [Serializable] Attributen markieren . Dadurch werden alle Mitglieder einer Klasse serialisiert, mit Ausnahme derjenigen, die als gekennzeichnet sind [NonSerialized].

Der folgende Code zeigt Ihnen, wie das geht:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;


namespace ConfigTest
{ [ Serializable() ]

    public class ConfigManager
    {
        private string windowTitle = "Corp";
        private string printTitle = "Inventory";

        public string WindowTitle
        {
            get
            {
                return windowTitle;
            }
            set
            {
                windowTitle = value;
            }
        }

        public string PrintTitle
        {
            get
            {
                return printTitle;
            }
            set
            {
                printTitle = value;
            }
        }
    }
}

Sie rufen dann in einer ConfigForm Ihre ConfigManager-Klasse auf und serialisieren sie!

public ConfigForm()
{
    InitializeComponent();
    cm = new ConfigManager();
    ser = new XmlSerializer(typeof(ConfigManager));
    LoadConfig();
}

private void LoadConfig()
{     
    try
    {
        if (File.Exists(filepath))
        {
            FileStream fs = new FileStream(filepath, FileMode.Open);
            cm = (ConfigManager)ser.Deserialize(fs);
            fs.Close();
        } 
        else
        {
            MessageBox.Show("Could not find User Configuration File\n\nCreating new file...", "User Config Not Found");
            FileStream fs = new FileStream(filepath, FileMode.CreateNew);
            TextWriter tw = new StreamWriter(fs);
            ser.Serialize(tw, cm);
            tw.Close();
            fs.Close();
        }    
        setupControlsFromConfig();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Nach der Serialisierung können Sie die Parameter Ihrer Konfigurationsdatei mit cm.WindowTitle usw. aufrufen.

kmote
quelle
5
Nur zur Verdeutlichung: Serializable und NonSerialized haben keine Auswirkungen auf XmlSerializer. Sie werden nur für System.Runtime.Serialization (z. B. binäre Serialisierung) verwendet. XmlSerializer serialisiert öffentliche Felder und (Lese- / Schreib-) Eigenschaften, nicht den internen Status: Für die Klasse ist kein Attribut erforderlich, und XmlIgnore anstelle von NonSerialized schließt ein Feld oder eine Eigenschaft aus.
Itowlson
@itowlson: Richtig. Bei der XML-Serialisierung werden mithilfe der Reflexion spezielle Klassen für die Serialisierung generiert.
Es würde beim Lesen des Codes helfen, wenn er ohne die zufällige Größe eingerückt wäre ...
Lasse V. Karlsen
@Lasse: Nicht sicher, was du meinst, aber wenn es zu schwer zu lesen ist, kannst du es bearbeiten
8

Wenn Ihre Sammlung zu groß wird, habe ich festgestellt, dass die XML-Serialisierung ziemlich langsam wird. Eine weitere Option zum Serialisieren Ihres Wörterbuchs wäre "Roll Your Own" mit einem BinaryReader und BinaryWriter.

Hier ist ein Beispielcode, um Ihnen den Einstieg zu erleichtern. Sie können diese generischen Erweiterungsmethoden für alle Arten von Wörterbüchern verwenden. Sie funktionieren recht gut, sind jedoch zu ausführlich, um sie hier zu veröffentlichen.

class Account
{
    public string AccountName { get; set; }
    public int AccountNumber { get; set; }

    internal void Serialize(BinaryWriter bw)
    {
        // Add logic to serialize everything you need here
        // Keep in synch with Deserialize
        bw.Write(AccountName);
        bw.Write(AccountNumber);
    }

    internal void Deserialize(BinaryReader br)
    {
        // Add logic to deserialize everythin you need here, 
        // Keep in synch with Serialize
        AccountName = br.ReadString();
        AccountNumber = br.ReadInt32();
    }
}


class Program
{
    static void Serialize(string OutputFile)
    {
        // Write to disk 
        using (Stream stream = File.Open(OutputFile, FileMode.Create))
        {
            BinaryWriter bw = new BinaryWriter(stream);
            // Save number of entries
            bw.Write(accounts.Count);

            foreach (KeyValuePair<string, List<Account>> accountKvp in accounts)
            {
                // Save each key/value pair
                bw.Write(accountKvp.Key);
                bw.Write(accountKvp.Value.Count);
                foreach (Account account in accountKvp.Value)
                {
                    account.Serialize(bw);
                }
            }
        }
    }

    static void Deserialize(string InputFile)
    {
        accounts.Clear();

        // Read from disk
        using (Stream stream = File.Open(InputFile, FileMode.Open))
        {
            BinaryReader br = new BinaryReader(stream);
            int entryCount = br.ReadInt32();
            for (int entries = 0; entries < entryCount; entries++)
            {
                // Read in the key-value pairs
                string key = br.ReadString();
                int accountCount = br.ReadInt32();
                List<Account> accountList = new List<Account>();
                for (int i = 0; i < accountCount; i++)
                {
                    Account account = new Account();
                    account.Deserialize(br);
                    accountList.Add(account);
                }
                accounts.Add(key, accountList);
            }
        }
    }

    static Dictionary<string, List<Account>> accounts = new Dictionary<string, List<Account>>();

    static void Main(string[] args)
    {
        string accountName = "Bob";
        List<Account> newAccounts = new List<Account>();
        newAccounts.Add(AddAccount("A", 1));
        newAccounts.Add(AddAccount("B", 2));
        newAccounts.Add(AddAccount("C", 3));
        accounts.Add(accountName, newAccounts);

        accountName = "Tom";
        newAccounts = new List<Account>();
        newAccounts.Add(AddAccount("A1", 11));
        newAccounts.Add(AddAccount("B1", 22));
        newAccounts.Add(AddAccount("C1", 33));
        accounts.Add(accountName, newAccounts);

        string saveFile = @"C:\accounts.bin";

        Serialize(saveFile);

        // clear it out to prove it works
        accounts.Clear();

        Deserialize(saveFile);
    }

    static Account AddAccount(string AccountName, int AccountNumber)
    {
        Account account = new Account();
        account.AccountName = AccountName;
        account.AccountNumber = AccountNumber;
        return account;
    }
}
GalacticJello
quelle
Vielen Dank, dies scheint die bisher beste Lösung zu sein. Was meinst du damit, mit Deserialize / Serialize synchron zu bleiben? Wie beim Aktualisieren der Datei, wenn sie geändert wird? Diese Funktion wird nur beim Starten und Beenden der Anwendung verwendet, um das Diktat zu speichern. Könnten Sie dies bitte klarstellen? Ansonsten vielen Dank.
George
Nachdem ich ein bisschen darüber nachgedacht habe, habe ich festgestellt, dass die Logik für Serialisierung und Deserialisierung dieselbe sein sollte. Das ist alles.
George
Ja, das ist alles was es bedeutet. Wenn Sie also eine weitere Eigenschaft zum Serialisieren / Deserialisieren hinzufügen, denken Sie daran, dass Sie der Serialize / Deserialize-Methode Code hinzufügen und diese in derselben Reihenfolge beibehalten müssen. Ein bisschen Wartung, aber die Leistung gegenüber der XML-Serialisierung ist kein Vergleich (einige Minuten zum Deserialisieren mit XML, einige Sekunden mit BinaryReader mit einigen hunderttausend Wörterbuchelementen).
GalacticJello
Vielen Dank, dies ist die perfekte Lösung
Sarath Vuyyuru
7

Eine vierte Option zu den von Ihnen erwähnten sind Binärdateien . Obwohl das geheimnisvoll und schwierig klingt, ist es mit der Serialisierungs-API in .NET wirklich einfach.

Unabhängig davon, ob Sie Binär- oder XML-Dateien auswählen, können Sie dieselbe Serialisierungs-API verwenden, obwohl Sie unterschiedliche Serialisierer verwenden würden.

Um eine Klasse binär zu serialisieren, muss sie mit dem Attribut [Serializable] gekennzeichnet sein oder ISerializable implementieren.

Sie können mit XML etwas Ähnliches tun , obwohl die Schnittstelle dort IXmlSerializable heißt und die Attribute [XmlRoot] und andere Attribute im System.Xml.Serialization-Namespace sind.

Wenn Sie eine relationale Datenbank verwenden möchten, ist SQL Server Compact Edition kostenlos und sehr leicht und basiert auf einer einzelnen Datei.

Mark Seemann
quelle
1
Flache Datei! = Textdatei. Ich würde denken, dass dies unter die Kategorie "Flat File" fallen würde.
Adam Robinson
2
Sie können eine Klasse binär serialisieren, unabhängig davon, ob Sie mit XML-Dateien
2
Dies ist der zuverlässigste Weg, es sei denn, das serialisierte Objekt muss für den Menschen lesbar sein. Es wird in eine winzige Datei serialisiert und schien immer der schnellste Weg zu sein, was die Geschwindigkeit des Codes angeht. Und Mark hat recht, es scheint arkan und schwierig, aber es ist überhaupt nicht. Und die binäre Serialisierung erfasst das GESAMTE Objekt, sogar seine privaten Mitglieder, was die XML-Serialisierung nicht tut.
CubanX
6

Ich habe gerade die Datenspeicherung für mein aktuelles Projekt beendet. Hier sind meine 5 Cent.

Ich habe mit der binären Serialisierung begonnen. Es war langsam (ungefähr 30 Sekunden beim Laden von 100.000 Objekten) und es wurde auch eine ziemlich große Datei auf der Festplatte erstellt. Die Implementierung dauerte jedoch einige Codezeilen und ich konnte alle Speicheranforderungen abdecken. Um eine bessere Leistung zu erzielen, habe ich die benutzerdefinierte Serialisierung übernommen. FastSerialization Framework von Tim Haynes für Code Project gefunden. In der Tat ist es ein paar Mal schneller (12 Sekunden zum Laden, 8 Sekunden zum Speichern, 100.000 Datensätze) und es benötigt weniger Speicherplatz. Das Framework basiert auf der Technik, die GalacticJello in einem früheren Beitrag beschrieben hat.

Dann bin ich zu SQLite gewechselt und konnte 2 mal 3 mal schnellere Leistung erzielen - 6 Sekunden für das Laden und 4 Sekunden für das Speichern von 100K-Datensätzen. Es umfasst das Parsen von ADO.NET-Tabellen nach Anwendungstypen. Es gab mir auch viel kleinere Datei auf der Festplatte. In diesem Artikel wird erläutert, wie Sie die beste Leistung von ADO.NET erzielen: http://sqlite.phxsoftware.com/forums/t/134.aspx . Das Generieren von INSERT-Anweisungen ist eine sehr schlechte Idee. Sie können sich vorstellen, wie ich davon erfahren habe. :) In der Tat hat mich die Implementierung von SQLite ziemlich viel Zeit gekostet und die Zeit, die so ziemlich jede Zeile des Codes benötigt, sorgfältig gemessen.

ACH
quelle
5

Das erste, was ich mir ansehen würde, ist eine Datenbank. Die Serialisierung ist jedoch eine Option. Wenn Sie sich für die binäre Serialisierung entscheiden, würde ich dies vermeiden BinaryFormatter - es besteht die Tendenz, dass Sie zwischen den Versionen wütend werden, wenn Sie Felder usw. ändern. XML via XmlSerialzierwäre in Ordnung und kann nebeneinander kompatibel sein (dh mit denselben Klassendefinitionen). mit protobuf-net, wenn Sie eine vertragsbasierte binäre Serialisierung ausprobieren möchten (ohne Aufwand einen Flatfile-Serializer).

Marc Gravell
quelle
4

Wenn Ihre Daten komplex und quantitativ sind oder lokal abgefragt werden müssen, sind Objektdatenbanken möglicherweise eine gültige Option. Ich würde vorschlagen , auf der Suche Db4o oder Karvonite .

Goran
quelle
3

Viele der Antworten in diesem Thread versuchen, die Lösung zu überarbeiten. Wenn ich richtig bin, möchten Sie nur die Benutzereinstellungen speichern.

Verwenden Sie dazu eine INI-Datei oder eine App.Config-Datei.

Wenn ich falsch liege und Sie Daten speichern, die mehr als nur Einstellungen sind, verwenden Sie eine flache Textdatei im CSV-Format. Diese sind schnell und einfach ohne den Aufwand von XML. Leute mögen es, diese zu poo poo, da sie nicht so elegant sind, nicht gut skalieren und in einem Lebenslauf nicht so gut aussehen, aber es könnte die beste Lösung für Sie sein, je nachdem, was Sie brauchen.

James
quelle
app.config vs benutzerdefiniertes XML: stackoverflow.com/questions/1565898/…
Ich mache etwas etwas komplexeres als nur Einstellungen. Jedem Benutzer können mehrere "Konten" mit seinem Namen verknüpft sein. Das Wörterbuch verknüpft diesen Namen (Zeichenfolge) mit der Liste der ihnen zugeordneten Konten. Ich würde eine Reihe von Konten für jeden Benutzer speichern. Es könnte mit XML funktionieren, aber ich bin mir nicht ganz sicher, wie ich es anstellen soll.
George
In diesem Fall würde ich die XmlSerializer-Klasse wie erwähnt verwenden. Wenn Sie OOP gut verstehen, sollte es einfach sein. Hier ist ein gutes Beispiel: jonasjohn.de/snippets/csharp/xmlserializer-example.htm
James
2

Ohne zu wissen, wie Ihre Daten aussehen, dh die Komplexität, Größe usw. XML ist einfach zu warten und leicht zugänglich. Ich würde KEINE Access-Datenbank verwenden, und Flatfiles sind auf lange Sicht schwieriger zu pflegen, insbesondere wenn Sie mit mehr als einem Datenfeld / -element in Ihrer Datei arbeiten.

Ich beschäftige mich täglich mit großen Flatfile-Datenfeeds in guten Mengen, und obwohl ein extremes Beispiel ist, sind Flatfile-Daten viel schwieriger zu pflegen als die von mir verarbeiteten XML-Datenfeeds.

Ein einfaches Beispiel für das Laden von XML-Daten in ein Dataset mit C #:

DataSet reportData = new DataSet();

reportData.ReadXml(fi.FullName);

Sie können auch LINQ to XML als Option zum Abfragen der XML-Daten auschecken ...

HTH ...

Tom Miller
quelle
1

Ich habe mehrere "eigenständige" Apps erstellt, die über einen lokalen Datenspeicher verfügen. Ich denke, die beste Verwendung wäre SQL Server Compact Edition (früher bekannt als SQLAnywhere).

Es ist leicht und kostenlos. Darüber hinaus können Sie beim Schreiben einer Datenzugriffsschicht bleiben, die in anderen Projekten wiederverwendbar ist. Wenn die App jemals auf einen größeren SQL-Server skaliert werden muss, müssen Sie nur die Verbindungszeichenfolge ändern.

HitLikeAHammer
quelle
1

Abhängig von der Komplexität Ihres Kontoobjekts würde ich entweder XML- oder Flatfile empfehlen.

Wenn für jedes Konto nur einige Werte gespeichert werden müssen, können Sie diese in einer Eigenschaftendatei wie folgt speichern:

account.1.somekey=Some value
account.1.someotherkey=Some other value
account.1.somedate=2009-12-21
account.2.somekey=Some value 2
account.2.someotherkey=Some other value 2

... und so weiter. Das Lesen aus einer Eigenschaftendatei sollte einfach sein, da es direkt einem Zeichenfolgenwörterbuch zugeordnet ist.

Der Speicherort dieser Datei ist am besten im AppData-Ordner in einem Unterordner für Ihr Programm zu speichern. Dies ist ein Ort, an dem aktuelle Benutzer immer Zugriff auf das Schreiben haben und der vom Betriebssystem selbst vor anderen Benutzern geschützt wird.

Pablo Venturino
quelle
0

Meine erste Neigung ist eine Zugangsdatenbank. Die MDB-Dateien werden lokal gespeichert und können bei Bedarf verschlüsselt werden. XML oder JSON würden jedoch auch für viele Szenarien funktionieren. Flatfiles würde ich nur für schreibgeschützte, nicht suchende (schreibgeschützte) Informationen verwenden. Ich bevorzuge das CSV-Format, um die Breite einzustellen.

Matthew Vines
quelle
2
Warum sollten Sie aus Neugier Access verwenden, wenn es nicht bereits vorhanden war oder Sie Zugriff von Access benötigen? Andernfalls scheint eine leichtgewichtige SQL-Engine empfehlenswerter zu sein, insbesondere wenn In-Process-Optionen wie SQLite und SQL Server CE verfügbar sind.
Adam Robinson
Die JET-Engine, mit der Sie .MDB-Dateien verwenden können, ist meiner Meinung nach mit Windows installiert, wodurch .MDB-Dateien als Lösung verwendet werden. Dies und die Tatsache, dass sie bei Zugriff leicht zu finden sind, wenn Sie dies tun müssen. Dies ist jedoch älter als die aktuelle Version von SQL Server CE, bei der es sich um eine DLL-Bereitstellung "xcopy" handeln kann, und ist daher ein besserer Weg, um ein weitgehend ähnliches Ergebnis zu erzielen.
Murph
15
Freunde lassen Freunde nicht Access verwenden
@Murph: Ja, JET ist jetzt eine Windows-Komponente, aber (wie Sie hervorheben) scheint die XCOPY-Bereitstellung (und das In-Process-Hosting) von SQL Server CE jeden Vorteil von JET zu beseitigen, während die Nachteile (begrenzt und ungerade) beibehalten werden SQL-Syntaxunterstützung, viele ORMs unterstützen sie nicht usw.). Also ... ich denke meine Frage steht immer noch, warum Sie es empfehlen würden :)
Adam Robinson
1
Wie fast alle meine Lehrer sagten: Zugang ist keine echte Datenbank :)
Florian K
0

Dies hängt von der Datenmenge ab, die Sie speichern möchten. In Wirklichkeit gibt es keinen Unterschied zwischen Flatfiles und XML. XML wäre wahrscheinlich vorzuziehen, da es dem Dokument eine Struktur verleiht. In der Praxis,

Die letzte Option, die derzeit von vielen Anwendungen verwendet wird, ist die Windows-Registrierung. Ich persönlich empfehle es nicht (Registry Bloat, Korruption, andere potenzielle Probleme), aber es ist eine Option.

Blacksol
quelle
Ein Bereich, in dem sich Flatfiles von XML unterscheiden, ist die Darstellung hierarchischer Daten. Sie können zwar Hierarchien in Einfachdateien darstellen, dies ist jedoch in XML einfacher.
Itowlson
0

Wenn Sie die binäre Serialisierungsroute wählen, berücksichtigen Sie die Geschwindigkeit, mit der auf ein bestimmtes Mitglied des Datums zugegriffen werden muss. Wenn es sich nur um eine kleine Sammlung handelt, ist das Laden der gesamten Datei sinnvoll. Wenn sie jedoch groß ist, können Sie auch eine Indexdatei in Betracht ziehen.

Das Verfolgen von Kontoeigenschaften / Feldern, die sich an einer bestimmten Adresse in der Datei befinden, kann Ihnen dabei helfen, die Zugriffszeit zu verkürzen, insbesondere wenn Sie diese Indexdatei basierend auf der Schlüsselverwendung optimieren. (Möglicherweise sogar, wenn Sie auf die Festplatte schreiben.)

Todd Richardson
quelle
0

Halten Sie es einfach - wie Sie sagten, ist eine flache Datei ausreichend. Verwenden Sie eine flache Datei.

Dies setzt voraus, dass Sie Ihre Anforderungen korrekt analysiert haben. Ich würde die Serialisierung als XML-Schritt überspringen, übertrieben für ein einfaches Wörterbuch. Gleiches gilt für eine Datenbank.

Larry Watanabe
quelle
0

Nach meiner Erfahrung reicht JSON in den meisten Fällen in einer Datei aus (meistens müssen Sie ein Array oder ein Objekt oder nur eine einzelne Zahl oder Zeichenfolge speichern). Ich brauche selten SQLite (das mehr Zeit benötigt, um es einzurichten und zu verwenden, meistens ist es übertrieben).

Tadej
quelle