如何在.NET (C#)中本地存储数据

81

我正在编写一个应用程序,以获取用户数据并在本地存储以供后续使用。该应用程序将经常启动和停止,并且我希望在应用程序启动/结束时保存/加载数据。

如果使用平面文件,它会非常简单,因为数据不需要得到保护(它只会存储在此台计算机上)。以下是我认为可选的选项:

  • 平面文件
  • XML
  • SQL数据库

与XML相比,平面文件需要更多的维护工作(没有像XML那样的内置类),但是我以前从未使用过XML,而且SQL似乎对这个相对简单的任务来说有些过头了。是否还有其他值得探索的方式?如果没有,哪个是最佳解决方案?


编辑:为了问题增加一些数据,基本上我想要存储的仅是像这样的字典:

Dictionary<string, List<Account>> 

其中 Account 是另一种自定义类型。

我是否应该将字典序列化为 xmlroot,然后将 Account 类型序列化为属性?


更新2:

因此可以序列化字典。让它变得复杂的是,这个字典的值本身是一个泛型,它是类型为 Account 的复杂数据结构列表。每个 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>

如您所见,层次结构如下:

  • 用户名 (字典中的字符串) >
  • 帐户 (列表中的每个帐户) >
  • 帐户数据 (即类属性)。

Dictionary<Username, List<Account>>获取此布局是棘手的问题,并且这也是本问题的重点。

这里有很多关于序列化的“如何”回答,这是我的错,因为我之前没有表述清楚,但现在我正在寻找一个明确的解决方案。


请提供有关应用程序类型、存储的数据以及预期大小的更多详细信息。 - AK_
3
用于序列化字典的方法: http://stackoverflow.com/questions/1111724 - Cheeso
19个回答

3
这个帖子中很多回答都试图过度设计解决方案。如果我没错的话,你只想存储用户设置。
为此,请使用 .ini 文件或 App.Config 文件。
如果我错了,并且您要存储的数据不仅仅是设置,请使用 csv 格式的平面文本文件。这些文件快速且易于使用,没有 XML 的开销。人们喜欢贬低它们,因为它们不够优雅,不具有良好的可扩展性,也不会在简历上看起来很好,但根据您的需求,这可能是最好的解决方案。

app.config与自定义XML:https://dev59.com/questions/YknSa4cB1Zd3GeqPRMsu - user195488
我正在做比设置稍微复杂一些的事情。每个用户可能会有多个与其名称相关联的“账户”。字典将此名称(字符串)链接到与其相关联的账户列表。我将为每个用户存储一堆账户。它可以使用XML来实现,但我不太确定如何着手。 - George
在这种情况下,我会使用XmlSerializer类,就像之前提到的那样。如果你对OOP有很好的掌握,那应该很容易。这是一个很好的例子:http://www.jonasjohn.de/snippets/csharp/xmlserializer-example.htm - James

2

如果不知道你的数据是什么样子,即复杂度、大小等等……XML易于维护且易于访问。我不会使用Access数据库,而且长期来看,平面文件更难以维护,特别是如果您在文件中处理多个数据字段/元素。

我每天都要处理大量的平面文件数据源,尽管这是一个极端的例子,但与处理的XML数据源相比,平面文件数据源要难得多。

以下是使用C#将XML数据加载到数据集中的简单示例:

DataSet reportData = new DataSet();

reportData.ReadXml(fi.FullName);

你也可以尝试使用LINQ to XML来查询XML数据。祝你好运!

1
根据您的账户对象的复杂程度,我建议您使用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文件夹中,放在程序的子文件夹中。这是一个当前用户始终可以访问写入的位置,并且由操作系统本身保护免受其他用户的干扰。


1

我已经完成了几个具有本地数据存储的“独立”应用程序。我认为最好使用的是SQL Server Compact Edition(以前称为SQLAnywhere)。

它很轻巧且免费。此外,您可以坚持编写可在其他项目中重复使用的数据访问层,如果应用程序需要扩展到像完整的SQL服务器这样的更大规模,您只需要更改连接字符串即可。


我不明白你所说的“曾经被称为SQLAnywhere”的意思。我看不出这两个产品之间的联系。https://en.wikipedia.org/wiki/SQL_Anywhere和https://en.wikipedia.org/wiki/SQL_Server_Compact - The incredible Jan

0

我的第一选择是访问数据库。.mdb文件存储在本地,如果需要可以进行加密。虽然XML或JSON也适用于许多场景。我只会将平面文件用于只读、非搜索(仅向前读取)信息。我倾向于使用csv格式来设置宽度。


2
出于好奇,除非Access已经存在或您需要从Access中访问它,否则为什么要使用Access?否则,似乎更建议使用轻量级的SQL引擎,特别是在进程内选项如SQLite和SQL Server CE可用的情况下。 - Adam Robinson
JET引擎允许您使用.MDB文件,我认为它已经随Windows安装了,这使得使用.MDB文件成为一种有吸引力的解决方案,还有一个原因是如果需要,可以很容易地通过Access进行挖掘。然而,这比当前版本的SQL Server CE更早,后者可以进行.DLL“xcopy”部署,因此是实现类似结果的更好方法。 - Murph
15
朋友不该让朋友使用 Access。 - user195488
@Murph:是的,JET现在是Windows组件,但(正如你所指出的),SQL Server CE的XCOPY部署(和进程内托管)似乎消除了JET的任何优势,同时保留了缺点(有限和奇怪的SQL语法支持,许多ORM不支持它等)。所以...我想知道为什么你会推荐它 :) - Adam Robinson
2
几乎所有我的老师都说过:Access 不是真正的数据库 :) - Florian K

0

这取决于您要存储的数据量。实际上,平面文件和XML之间没有区别。由于XML提供了文档结构,因此可能更可取。在实践中,

最后一个选项,许多应用程序现在使用的是Windows注册表。我个人不建议使用它(注册表膨胀、损坏、其他潜在问题),但这是一种选择。


平面文件与XML不同的一个领域是表示分层数据。你可以在平面文件中表示层次结构,但在XML中更容易实现。 - itowlson

0

如果您选择采用二进制序列化方法,请考虑访问特定数据成员的速度。如果只是一个小集合,加载整个文件是有意义的,但如果它很大,您可能还需要考虑使用索引文件。

跟踪位于文件中特定地址的帐户属性/字段可以帮助您加快访问时间,特别是如果您根据关键使用情况优化该索引文件。(甚至在写入磁盘时)


0

保持简单 - 正如您所说,平面文件就足够了。使用平面文件。

这是在假设您已经正确分析了您的需求的情况下。对于一个简单的字典来说,我会跳过将其序列化为 XML 的步骤,这是过度设计。同样的事情也适用于数据库。


0
在我的经验中,大多数情况下文件中的JSON就足够了(通常你只需要存储一个数组、对象、单个数字或字符串)。我很少需要SQLite(它需要更多时间来设置和使用,大多数情况下都是杀鸡焉用牛刀)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接