Лучший способ хранить данные локально в .NET (C #)

Я пишу приложение, которое берет пользовательские данные и хранит их локально для дальнейшего использования. Приложение будет запускаться и останавливаться довольно часто, и я бы хотел, чтобы оно сохраняло / загружало данные при запуске / завершении приложения.

Было бы довольно просто, если бы я использовал плоские файлы, поскольку данные действительно не нуждаются в защите (они будут храниться только на этом ПК). Я считаю, что следующие варианты:

  • Плоские файлы
  • XML
  • БД SQL

Плоские файлы требуют немного больше усилий для обслуживания (без встроенных классов, как с XML), однако я раньше не использовал XML, и SQL кажется излишним для этой относительно простой задачи.

Есть ли другие возможности, которые стоит изучить? Если нет, то какое из них лучшее решение?


Изменить: чтобы добавить немного больше данных к проблеме, в основном единственное, что я хотел бы сохранить, - это словарь, который выглядит так

Dictionary<string, List<Account>> 

где Account - другой настраиваемый тип.

Могу ли я сериализовать dict как xmlroot, а затем тип Account как атрибуты?


Обновление 2:

Так что можно сериализовать словарь. Сложность состоит в том, что значение этого dict само по себе является универсальным, которое представляет собой список сложных структур данных типа Account. Каждая учетная запись довольно проста, это просто набор свойств.

Насколько я понимаю, цель здесь - попытаться прийти к следующему:

<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>

Как видите, иерархия

  • Имя пользователя (строка dict)>
  • Учетная запись (каждая учетная запись в Списке)>
  • Данные учетной записи (т.е. свойства класса).

Получить этот макет от Dictionary<Username, List<Account>> - непростая задача, и суть этого вопроса.

Здесь много ответов о сериализации, что является моей ошибкой, поскольку я не прояснил это на раннем этапе, но теперь я ищу определенное решение.


person George    schedule 21.12.2009    source источник
comment
дать больше подробностей о типе приложения и хранимых данных, а также ожидаемый размер   -  person AK_    schedule 21.12.2009
comment
Для сериализации словаря: stackoverflow.com/questions/1111724   -  person Cheeso    schedule 21.12.2009


Ответы (19)


Я бы сохранил файл как JSON. Поскольку вы храните словарь, который представляет собой просто список пар имя / значение, то это в значительной степени то, для чего был разработан json.
Существует довольно много приличных бесплатных json-библиотек .NET - вот one, но вы можете найти полный список по первой ссылке.

person zebrabox    schedule 21.12.2009
comment
json немного необычен для локального хранилища, но это определенно отличное решение. Особенно с такой библиотекой, как Newtonsoft Json.NET - person AFract; 30.06.2014
comment
вместо того, чтобы полагаться на стороннюю библиотеку, я бы сохранил данные, используя встроенный тип набора данных, который очень просто записать на диск (см. пример Тома Миллера ниже) - person EKanadily; 12.12.2016

Это действительно зависит от того, что вы храните. Если вы говорите о структурированных данных, то вам подойдет XML или очень легкая СУБД SQL, такая как SQLite или SQL Server Compact Edition. Решение SQL становится особенно привлекательным, если размер данных превышает тривиальный размер.

Если вы храните большие фрагменты относительно неструктурированных данных (например, бинарные объекты, такие как изображения), очевидно, что ни база данных, ни XML-решение не подходят, но, учитывая ваш вопрос, я предполагаю, что это скорее первое, чем второе.

person Adam Robinson    schedule 21.12.2009
comment
Конфигурационные файлы XML должны быть структурированы? - person ; 21.12.2009
comment
@Roboto: XML по определению структурирован. Однако это не означает, что вы должны использовать их строго структурированно. - person Adam Robinson; 21.12.2009

Все вышеперечисленное является хорошими ответами и в целом решает проблему.

Если вам нужен простой и бесплатный способ масштабирования до миллионов фрагментов данных, попробуйте проект ESENT Managed Interface на GitHub или из NuGet.

ESENT - это встраиваемый механизм хранения баз данных (ISAM), который является частью Windows. Он обеспечивает надежное, синхронизированное, одновременное и высокопроизводительное хранилище данных с блокировкой на уровне строк, журналированием с упреждающей записью и изоляцией моментальных снимков. Это управляемая оболочка для ESENT Win32 API.

У него есть объект PersistentDictionary, который довольно прост в использовании. Думайте об этом как об объекте Dictionary (), но он автоматически загружается и сохраняется на диск без дополнительного кода.

Например:

/// <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();
    }

Чтобы ответить на вопрос Джорджа:

Поддерживаемые типы ключей

В качестве ключей словаря поддерживаются только эти типы:

Логический байт Int16 UInt16 Int32 UInt32 Int64 UInt64 Float Double Guid DateTime TimeSpan String

Поддерживаемые типы значений

Значения словаря могут быть любыми из типов ключей, допускающими значение NULL версиями типов ключей, Uri, IPAddress или сериализуемой структурой. Структура считается сериализуемой, только если она соответствует всем этим критериям:

• Структура помечена как сериализуемая. • Каждый член структуры может быть: 1. Примитивным типом данных (например, Int32) 2. Строкой, Uri или IP-адресом 3. Сериализуемой структурой.

Или, другими словами, сериализуемая структура не может содержать никаких ссылок на объект класса. Это сделано для сохранения согласованности API. Добавление объекта в PersistentDictionary создает копию объекта посредством сериализации. Изменение исходного объекта не приведет к изменению копии, что приведет к запутанному поведению. Чтобы избежать этих проблем, PersistentDictionary будет принимать только типы значений в качестве значений.

Можно сериализовать [сериализуемый] struct Good {public DateTime? Получила; публичная строка Имя; публичная десятичная цена; общедоступный Uri Url; }

Невозможно сериализовать [Serializable] struct Bad {public byte [] Data; // массивы не поддерживаются public Exception Error; // ссылочный объект}

person GalacticJello    schedule 21.12.2009
comment
Этот метод в основном заменяет встроенный универсальный словарь постоянным. Это довольно элегантное решение, но как оно обрабатывает сложные объекты, как в примере с OP? Он хранит все внутри дикта или только сам диктант? - person George; 21.12.2009
comment
Это может не соответствовать конечной цели - попытке сохранить списки типа Account. Ключ был бы в порядке, но сделать общий сериализуемый может быть сложно: /. - person George; 21.12.2009
comment
Любой другой, реализующий это, может выиграть, зная, что вы можете использовать Nuget для получения ManagedEsent. Затем вам нужно сослаться на Esent.Collections.DLL и Esent.ISAM.DLL. Затем добавьте using Microsoft.Isam.Esent.Collections.Generic; чтобы получить тип PersistentDictionary. DLL коллекций, возможно, придется загрузить из раздела загрузок на managedesent.codeplex.com - person Steve Hibbert; 03.05.2017
comment
ManagedEsent превратился в Microsoft.Database.ManagedEsent. Вместо этого следует использовать Microsoft.Database.Collections.Generic из nuget, поскольку он включает как ManagedEsent, так и ISAM. - person VoteCoffee; 14.05.2020

XML прост в использовании благодаря сериализации. Используйте Изолированное хранилище.

См. Также Как решить, где хранить состояние для каждого пользователя? Реестр? Данные приложения? Изолированное хранилище?

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();
    }
}
person Cheeso    schedule 21.12.2009
comment
Это не очень портативный и не изящный - person ; 21.12.2009
comment
Это похоже на код вырезания и вставки, чтобы вы могли стать первым постером. Было бы лучше просто придерживаться ваших ссылок. - person ; 21.12.2009
comment
Ну да, я вырезал это прямо из написанного мной приложения, которое делает это. Робото, в чем твоя проблема? - person Cheeso; 22.12.2009
comment
Он даже не использует инъекцию зависимостей! Вы не получили записку? - person Steve Smith; 22.11.2016
comment
Я согласен с рекомендацией XML, но, попробовав это сам, я столкнулся с ограничением изолированного хранилища - он создает разные файлы в зависимости от сборки, из которой выполняется код. Закончилось просто с помощью AppData \ Roaming через Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"{AppName}\{FileName}.XML"); - person Ory Zaidenvorm; 08.12.2016
comment
Теперь у вас неработающая ссылка. - person ΩmegaMan; 25.09.2020

Я рекомендую класс чтения / записи XML для файлов, потому что он легко сериализуется.

Сериализация в C #

Сериализация (известная как травление в Python) - это простой способ преобразовать объект в двоичное представление, которое затем может быть, например, записываются на диск или отправляются по сети.

Это полезно, например, для удобного сохранения настроек в файл.

Вы можете сериализовать свои собственные классы, если пометите их атрибутом [Serializable]. Это сериализует все члены класса, кроме отмеченных как [NonSerialized].

Ниже приведен код, показывающий, как это сделать:

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;
            }
        }
    }
}

Затем вы, возможно, в ConfigForm, вызываете свой класс ConfigManager и сериализуете его!

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);
    }
}

После того, как он был сериализован, вы можете вызвать параметры вашего файла конфигурации, используя cm.WindowTitle и т. Д.

person Community    schedule 21.12.2009
comment
Чтобы прояснить: Serializable и NonSerialized никак не влияют на XmlSerializer; они используются только для System.Runtime.Serialization (например, двоичной сериализации). XmlSerializer сериализует общедоступные поля и (чтение-запись) свойства, а не внутреннее состояние: атрибут не требуется в классе, и XmlIgnore вместо NonSerialized для исключения поля или свойства. - person itowlson; 21.12.2009
comment
@itowlson: Верно. Сериализация XML использует отражение для создания специальных классов для выполнения сериализации. - person ; 21.12.2009
comment
Было бы полезно при чтении кода, если бы он был с отступом без случайного размера ... - person Lasse V. Karlsen; 23.12.2009
comment
@Lasse: Не понимаю, что вы имеете в виду, но если его сложно читать, вы можете отредактировать его - person ; 23.12.2009

Я обнаружил, что если ваша коллекция становится слишком большой, сериализация Xml выполняется довольно медленно. Другой вариант сериализации вашего словаря - это «свернуть свой собственный» с помощью BinaryReader и BinaryWriter.

Вот пример кода, чтобы вы начали. Вы можете сделать эти общие методы расширения для обработки любого типа словаря, и он работает достаточно хорошо, но слишком подробен, чтобы публиковать его здесь.

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;
    }
}
person GalacticJello    schedule 21.12.2009
comment
Спасибо, это пока что кажется лучшим решением. Что вы имеете в виду под синхронизацией с десериализацией / сериализацией? Как обновить файл при его изменении? Эта функция будет использоваться только при запуске и выходе приложения для сохранения словаря, не могли бы вы это пояснить? В противном случае большое спасибо. - person George; 22.12.2009
comment
Поразмыслив немного над этим, я понял, что это означает, что логика сериализации и десериализации должна быть одинаковой. Вот и все. - person George; 22.12.2009
comment
Да, это все, что это значит. Поэтому, если вы добавляете другое свойство для сериализации / десериализации, просто имейте в виду, что вам нужно добавить код как для метода Serialize / Deserialize, так и сохранить их в том же порядке. Немного поддержки, но производительность по сравнению с сериализацией Xml несравнима (несколько минут для десериализации с использованием xml, пара секунд с использованием BinaryReader с несколькими сотнями тысяч элементов словаря). - person GalacticJello; 22.12.2009
comment
Спасибо это идеальное решение - person Sarath Vuyyuru; 16.10.2012

Четвертый вариант из упомянутых вами - двоичные файлы. Хотя это звучит загадочно и сложно, с API сериализации в .NET это действительно просто.

Независимо от того, выбираете ли вы двоичные или XML-файлы, вы можете использовать один и тот же API-интерфейс сериализации, хотя вы должны использовать разные сериализаторы.

Для двоичной сериализации класса он должен быть помечен атрибутом [Serializable] или реализован ISerializable.

Вы можете сделать что-то подобное с XML, хотя там интерфейс называется IXmlSerializable, а атрибуты - [XmlRoot] и другие атрибуты в пространстве имен System.Xml.Serialization.

Если вы хотите использовать реляционную базу данных, SQL Server Compact Edition бесплатен, очень легкий и основан на одном файле.

person Mark Seemann    schedule 21.12.2009
comment
Плоский файл! = Текстовый файл. Я бы подумал, что это попадает в категорию плоских файлов. - person Adam Robinson; 21.12.2009
comment
Вы можете двоично сериализовать класс независимо от того, имеете ли вы дело с файлами XML. - person ; 21.12.2009
comment
если вам не нужно, чтобы сериализованный объект был удобочитаемым, это самый надежный способ. Он сериализуется в крошечный файл и всегда казался самым быстрым способом сделать это с точки зрения скорости выполнения кода. И Марк прав, это кажется загадочным и сложным, но это совсем не так. А двоичная сериализация захватывает ВЕСЬ объект, даже его частные члены, чего не делает сериализация XML. - person CubanX; 21.12.2009

Только что закончил кодирование хранилища данных для моего текущего проекта. Вот мои 5 центов.

Я начал с двоичной сериализации. Это было медленно (около 30 секунд для загрузки 100 000 объектов), а также создавало довольно большой файл на диске. Однако для реализации мне потребовалось несколько строк кода, и все мои потребности в хранилище были покрыты. Чтобы повысить производительность, я перешел на настраиваемую сериализацию. Нашел фреймворк FastSerialization Тимом Хейнсом в Code Project. Действительно, он в несколько раз быстрее (12 секунд на загрузку, 8 секунд на сохранение, 100К записей) и занимает меньше места на диске. Фреймворк построен на методе, описанном GalacticJello в предыдущем посте.

Затем я перешел на SQLite и смог получить в 2 или 3 раза более высокую производительность - 6 секунд для загрузки и 4 секунды для сохранения, 100K записей. Он включает анализ таблиц ADO.NET по типам приложений. Это также дало мне намного меньший файл на диске. В этой статье объясняется, как добиться максимальной производительности от ADO.NET: http://sqlite.phxsoftware.com/forums/t/134.aspx. Создание операторов INSERT - очень плохая идея. Вы можете догадаться, как я узнал об этом. :) Действительно, реализация SQLite заняла у меня довольно много времени плюс тщательное измерение времени, которое уходит почти на каждую строчку кода.

person ACH    schedule 23.12.2009

Первое, на что я обращаю внимание, - это база данных. Однако сериализация - это вариант. Если вы выберете двоичную сериализацию, я бы избегал BinaryFormatter - он имеет тенденцию злиться между версиями, если вы меняете поля и т. Д. Xml через XmlSerialzier подойдет, и может быть рядом совместим (т.е. с теми же определениями классов) с protobuf-net, если вы хотите попробовать двоичную сериализацию на основе контрактов (что дает вам сериализатор плоских файлов без каких-либо усилий).

person Marc Gravell    schedule 21.12.2009

Если ваши данные сложны, их много или вам нужно запрашивать их локально, то объектные базы данных могут быть подходящим вариантом. Я бы посоветовал посмотреть Db4o или Карвонит.

person Goran    schedule 21.12.2009

Многие ответы в этой теме пытаются перестроить решение. Если я прав, вы просто хотите сохранить пользовательские настройки.

Используйте для этого файл .ini или файл App.Config.

Если я ошибаюсь, и вы храните данные, которые представляют собой нечто большее, чем просто настройки, используйте простой текстовый файл в формате csv. Это быстро и легко, без накладных расходов на XML. Людям нравится обманывать их, потому что они не такие элегантные, плохо масштабируются и не так хорошо выглядят в резюме, но это может быть лучшим решением для вас, в зависимости от того, что вам нужно.

person James    schedule 21.12.2009
comment
app.config против пользовательского XML: stackoverflow.com / questions / 1565898 / - person ; 21.12.2009
comment
Я делаю что-то более сложное, чем просто настройки. У каждого пользователя может быть несколько учетных записей, связанных с его именем. Словарь связывает это имя (строку) со списком связанных с ними учетных записей. Я буду хранить несколько учетных записей для каждого пользователя. Он может работать с xml, но я не совсем уверен, как это сделать. - person George; 21.12.2009
comment
В этом случае я бы использовал класс XmlSerializer, как упоминалось. Если вы хорошо разбираетесь в ООП, это должно быть легко. Вот хороший пример: jonasjohn.de/snippets/csharp/xmlserializer-example.htm - person James; 23.12.2009

Не зная, как выглядят ваши данные, т.е. сложность, размер и т. Д. XML легко поддерживать и легко доступен. Я бы НЕ использовал базу данных Access, а плоские файлы труднее поддерживать в течение длительного времени, особенно если вы имеете дело с более чем одним полем / элементом данных в вашем файле.

Я ежедневно имею дело с большими потоками данных в виде плоских файлов в больших количествах, и даже несмотря на крайний пример, данные в виде плоских файлов намного сложнее поддерживать, чем потоки данных XML, которые я обрабатываю.

Простой пример загрузки XML-данных в набор данных с использованием C #:

DataSet reportData = new DataSet();

reportData.ReadXml(fi.FullName);

Вы также можете проверить LINQ to XML как вариант для запроса данных XML ...

HTH ...

person Tom Miller    schedule 21.12.2009

Я сделал несколько «автономных» приложений с локальным хранилищем данных. Я думаю, что лучше всего использовать SQL Server Compact Edition (ранее известный как SQLAnywhere).

Он легкий и бесплатный. Кроме того, вы можете придерживаться написания уровня доступа к данным, который можно повторно использовать в других проектах, плюс, если приложению когда-либо понадобится масштабироваться до чего-то большего, например, полномасштабного SQL-сервера, вам нужно только изменить строку подключения.

person HitLikeAHammer    schedule 21.12.2009

В зависимости от сложности объекта вашей учетной записи я бы рекомендовал либо XML, либо плоский файл.

Если для каждой учетной записи нужно сохранить всего пару значений, вы можете сохранить их в файле свойств, например:

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

... и так далее. Чтение из файла свойств должно быть простым, так как он напрямую отображается в строковый словарь.

Что касается места для хранения этого файла, лучше всего было бы сохранить его в папке AppData внутри подпапки вашей программы. Это место, где текущие пользователи всегда будут иметь доступ для записи, и оно защищено от других пользователей самой ОС.

person Pablo Venturino    schedule 21.12.2009

Моя первая склонность - это база данных доступа. Файлы .mdb хранятся локально и могут быть зашифрованы, если это будет сочтено необходимым. Хотя XML или JSON также будут работать для многих сценариев. Плоские файлы я бы использовал только для информации только для чтения, без поиска (только для прямого чтения). Я предпочитаю формат csv для установки ширины.

person Matthew Vines    schedule 21.12.2009
comment
Из любопытства, зачем вам использовать Access, если он уже не существует или вам нужен доступ к нему из, ну, Access? В противном случае кажется, что облегченный механизм SQL был бы более целесообразным, особенно с доступными внутрипроцессными параметрами, такими как SQLite и SQL Server CE. - person Adam Robinson; 21.12.2009
comment
Я думаю, что JET-движок, который позволяет вам использовать файлы .MDB, установлен с окнами, что позволяет использовать файлы .MDB в качестве решения, а также тот факт, что к ним легко получить доступ, если вы нужно. Однако это предшествовало текущему воплощению SQL Server CE, которое может быть развертыванием .DLL xcopy и, следовательно, является лучшим способом достижения в целом аналогичного результата. - person Murph; 21.12.2009
comment
Друзья не разрешают друзьям использовать Access - person ; 21.12.2009
comment
@Murph: Да, JET сейчас является компонентом Windows, но (как вы указываете) развертывание XCOPY (и внутрипроцессный хостинг) SQL Server CE, похоже, устраняет любые преимущества JET, сохраняя при этом недостатки (ограниченные и странные Поддержка синтаксиса SQL, многие ORM его не поддерживают и т. Д.). Итак ... я думаю, мой вопрос все еще в том, почему вы бы порекомендовали это :) - person Adam Robinson; 21.12.2009
comment
Как утверждали почти все мои учителя: Access - это не настоящая база данных :) - person Florian K; 07.03.2017

Это зависит от количества данных, которые вы хотите сохранить. На самом деле нет разницы между плоскими файлами и XML. XML, вероятно, был бы предпочтительнее, поскольку он обеспечивает структуру документа. На практике,

Последний вариант, которым сейчас пользуются многие приложения, - это реестр Windows. Я лично не рекомендую это (раздувание реестра, повреждение, другие потенциальные проблемы), но это вариант.

person blacksol    schedule 21.12.2009
comment
Одна область, в которой плоские файлы отличаются от XML, - это представление иерархических данных. Конечно, вы можете представлять иерархии в плоских файлах, но это проще сделать в XML. - person itowlson; 21.12.2009

Если вы идете по маршруту двоичной сериализации, рассмотрите скорость, с которой необходимо получить доступ к конкретному элементу данных. Если это небольшая коллекция, загрузка всего файла будет иметь смысл, но если она будет большой, вы также можете рассмотреть возможность создания индексного файла.

Свойства / поля учетной записи отслеживания, расположенные по определенному адресу в файле, могут помочь вам ускорить время доступа, особенно если вы оптимизируете этот индексный файл на основе использования ключа. (возможно, даже при записи на диск.)

person Todd Richardson    schedule 21.12.2009

Будьте проще - как вы сказали, достаточно простого файла. Используйте плоский файл.

Предполагается, что вы правильно проанализировали свои требования. Я бы пропустил сериализацию как шаг XML, слишком большой для простого словаря. То же самое и с базой данных.

person Larry Watanabe    schedule 21.12.2009

По моему опыту, в большинстве случаев достаточно JSON в файле (в основном вам нужно хранить массив или объект или просто одно число или строку). Мне редко нужен SQLite (для его настройки и использования требуется больше времени, в большинстве случаев это излишне).

person Tadej    schedule 12.05.2017