在 .NET (C#) 中本地存储数据的最佳方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1941928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to store data locally in .NET (C#)
提问by George
I'm writing an application that takes user data and stores it locally for use later. The application will be started and stopped fairly often, and I'd like to make it save/load the data on application start/end.
我正在编写一个应用程序,它获取用户数据并将其存储在本地以备后用。应用程序将经常启动和停止,我想让它在应用程序启动/结束时保存/加载数据。
It'd be fairly straightforward if I used flat files, as the data doesn't really need to be secured (it'll only be stored on this PC). The options I believe are thus:
如果我使用平面文件会相当简单,因为数据并不真正需要保护(它只会存储在这台 PC 上)。因此,我相信的选择是:
- Flat files
- XML
- SQL DB
- 平面文件
- XML
- 数据库
Flat files require a bit more effort to maintain (no built in classes like with XML), however I haven't used XML before, and SQL seems like overkill for this relatively easy task.
平面文件需要更多的维护工作(没有像 XML 那样的内置类),但是我以前没有使用过 XML,对于这个相对简单的任务,SQL 似乎有点过分。
Are there any other avenues worth exploring? If not, which of these is the best solution?
还有其他值得探索的途径吗?如果没有,以下哪个是最佳解决方案?
Edit: To add a little more data to the problem, basically the only thing I'd like to store is a Dictionary that looks like this
编辑:要向问题添加更多数据,基本上我唯一想存储的是一个看起来像这样的字典
Dictionary<string, List<Account>>
where Account is another custom type.
其中 Account 是另一种自定义类型。
Would I serialize the dict as the xmlroot, and then the Account type as attributes?
我会将 dict 序列化为 xmlroot,然后将 Account 类型序列化为属性吗?
Update 2:
更新 2:
So it's possible to serialize a dictionary. What makes it complicated is that the value for this dict is a generic itself, which is a list of complex data structures of type Account. Each Account is fairly simple, it's just a bunch of properties.
因此可以序列化字典。让它变得复杂的是,这个 dict 的值本身就是一个泛型,它是一个类型为 Account 的复杂数据结构的列表。每个 Account 都相当简单,它只是一堆属性。
It is my understanding that the goal here is to try and end up with this:
我的理解是,这里的目标是尝试并以此结束:
<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>
As you can see the heirachy is
正如你所看到的,heirachy 是
- Username (string of dict) >
- Account (each account in the List) >
- Account data (ie class properties).
- 用户名(字典字符串)>
- 帐户(列表中的每个帐户)>
- 帐户数据(即类属性)。
Obtaining this layout from a Dictionary<Username, List<Account>>
is the tricky bit, and the essence of this question.
从 a 获取这个布局Dictionary<Username, List<Account>>
是一个棘手的问题,也是这个问题的本质。
There are plenty of 'how to' responses here on serialisation, which is my fault since I didn't make it clearer early on, but now I'm looking for a definite solution.
关于序列化,这里有很多“如何做”的回应,这是我的错,因为我没有尽早说清楚,但现在我正在寻找一个明确的解决方案。
采纳答案by zebrabox
I'd store the file as JSON. Since you're storing a dictionary which is just a name/value pair list then this is pretty much what json was designed for.
There a quite a few decent, free .NET json libraries - here's onebut you can find a full list on the first link.
我将文件存储为JSON。由于您存储的字典只是一个名称/值对列表,因此这几乎就是 json 的设计目的。
有很多不错的免费 .NET json 库 - 这是一个,但您可以在第一个链接上找到完整列表。
回答by Cheeso
XML is easy to use, via serialization. Use Isolated storage.
通过序列化,XML 易于使用。使用隔离存储。
See also How to decide where to store per-user state? Registry? AppData? Isolated Storage?
另请参阅如何决定在何处存储每个用户的状态?注册表?应用程序数据?隔离存储?
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();
}
}
回答by Adam Robinson
It really depends on what you're storing. If you're talking about structured data, then either XML or a very lightweight SQL RDBMS like SQLite or SQL Server Compact Edition will work well for you. The SQL solution becomes especially compelling if the data moves beyond a trivial size.
这实际上取决于您存储的内容。如果您在谈论结构化数据,那么 XML 或非常轻量级的 SQL RDBMS(如 SQLite 或 SQL Server Compact Edition)都适合您。如果数据超出了微不足道的大小,SQL 解决方案就会变得特别引人注目。
If you're storing large pieces of relatively unstructured data (binary objects like images, for example) then obviously neither a database nor XML solution are appropriate, but given your question I'm guessing it's more of the former than the latter.
如果您要存储大量相对非结构化的数据(例如,像图像这样的二进制对象),那么显然数据库和 XML 解决方案都不合适,但鉴于您的问题,我猜前者比后者更重要。
回答by Matthew Vines
My first inclination is an access database. The .mdb files are stored locally, and can be encrypted if that is deemed necessary. Though XML or JSON would also work for many scenarios. Flat files I would only use for read only, non-search (forward read only) information. I tend to prefer csv format to set width.
我的第一个倾向是访问数据库。.mdb 文件存储在本地,如果需要,可以加密。尽管 XML 或 JSON 也适用于许多场景。平面文件我只会用于只读、非搜索(前向只读)信息。我倾向于使用 csv 格式来设置宽度。
回答by Mark Seemann
A fourth option to those you mention are binary files. Although that sounds arcane and difficult, it's really easy with the serialization API in .NET.
你提到的第四个选项是二进制文件。尽管这听起来既神秘又困难,但使用 .NET 中的序列化 API 确实很容易。
Whether you choose binary or XML files, you can use the same serialization API, although you would use different serializers.
无论您选择二进制文件还是 XML 文件,您都可以使用相同的序列化 API,尽管您会使用不同的序列化程序。
To binary serialize a class, it must be marked with the [Serializable] attribute or implement ISerializable.
要二进制序列化一个类,它必须用 [Serializable] 属性标记或实现 ISerializable。
You can do something similar with XML, although there the interface is called IXmlSerializable, and the attributes are [XmlRoot] and other attributes in the System.Xml.Serialization namespace.
您可以对XML执行类似的操作,尽管该接口称为 IXmlSerializable,并且属性是 [XmlRoot] 和 System.Xml.Serialization 命名空间中的其他属性。
If you want to use a relational database, SQL Server Compact Editionis free and very lightweight and based on a single file.
如果您想使用关系数据库,SQL Server Compact Edition是免费的、非常轻量级的并且基于单个文件。
回答by blacksol
It depends on the amount of data you are looking to store. In reality there's no difference between flat files and XML. XML would probably be preferable since it provides a structure to the document. In practice,
这取决于您要存储的数据量。实际上,平面文件和 XML 之间没有区别。XML 可能更可取,因为它为文档提供了结构。在实践中,
The last option, and a lot of applications use now is the Windows Registry. I don't personally recommend it (Registry Bloat, Corruption, other potential issues), but it is an option.
最后一个选项,现在很多应用程序使用的是 Windows 注册表。我个人不推荐它(注册表膨胀、腐败、其他潜在问题),但它是一种选择。
回答by blacksol
I recommend XML reader/writer class for files because it is easily serialized.
我推荐文件的 XML 读取器/写入器类,因为它很容易序列化。
Serialization (known as pickling in python) is an easy way to convert an object to a binary representation that can then be e.g. written to disk or sent over a wire.
It's useful e.g. for easy saving of settings to a file.
You can serialize your own classes if you mark them with
[Serializable]
attribute. This serializes all members of a class, except those marked as[NonSerialized]
.
序列化(在 Python 中称为酸洗)是一种将对象转换为二进制表示的简单方法,然后可以将其写入磁盘或通过网络发送。
它非常有用,例如可以轻松地将设置保存到文件中。
如果您用
[Serializable]
属性标记它们,您可以序列化您自己的类。这将序列化一个类的所有成员,除了标记为[NonSerialized]
.
The following is code to show you how to do this:
以下是向您展示如何执行此操作的代码:
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;
}
}
}
}
You then, in maybe a ConfigForm, call your ConfigManager class and Serialize it!
然后,您可能在 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);
}
}
After it has been serialized, you can then call the parameters of your config file using cm.WindowTitle, etc.
序列化后,您可以使用 cm.WindowTitle 等调用配置文件的参数。
回答by Tom Miller
Without knowing what your data looks like, i.e. the complexity, size, etc...XML is easy to maintain and easily accessible. I would NOT use an Access database, and flat files are more difficult to maintain over the long haul, particularly if you are dealing with more than one data field/element in your file.
在不知道您的数据是什么样子的情况下,即复杂性、大小等...XML 易于维护且易于访问。我不会使用 Access 数据库,从长远来看,平面文件更难维护,尤其是当您处理文件中的多个数据字段/元素时。
I deal with large flat-file data feeds in good quantities daily, and even though an extreme example, flat-file data is much more difficult to maintain than the XML data feeds I process.
我每天都会处理大量的大型平面文件数据提要,尽管是一个极端的例子,但与我处理的 XML 数据提要相比,维护平面文件数据要困难得多。
A simple example of loading XML data into a dataset using C#:
使用 C# 将 XML 数据加载到数据集的简单示例:
DataSet reportData = new DataSet();
reportData.ReadXml(fi.FullName);
You can also check out LINQ to XML as an option for querying the XML data...
您还可以查看 LINQ to XML 作为查询 XML 数据的选项...
HTH...
哈...
回答by HitLikeAHammer
I have done several "stand alone" apps that have a local data store. I think the best thing to use would be SQL Server Compact Edition (formerly known as SQLAnywhere).
我已经完成了几个具有本地数据存储的“独立”应用程序。我认为最好使用的是 SQL Server Compact Edition(以前称为 SQLAnywhere)。
It's lightweight and free. Additionally, you can stick to writing a data access layer that is reusable in other projects plus if the app ever needs to scale to something bigger like full blown SQL server, you only need to change the connection string.
它轻巧且免费。此外,您可以坚持编写可在其他项目中重用的数据访问层,此外,如果应用程序需要扩展到更大的东西,例如成熟的 SQL 服务器,您只需要更改连接字符串。
回答by Todd Richardson
If you go the binary serialization route, Consider the speed at which a particular member of the datum needs to be accessed. If it is only a small collection, loading the whole file will make sense, but if it will be large, you might also consider an index file.
如果您采用二进制序列化路线,请考虑需要访问数据特定成员的速度。如果它只是一个小集合,加载整个文件是有意义的,但如果它很大,你也可以考虑一个索引文件。
Tracking Account Properties/fields that are located at a specific address within the file can help you speed up access time, especially if you optimize that index file based on key usage. (possibly even when you write to disk.)
跟踪位于文件内特定地址的帐户属性/字段可以帮助您加快访问时间,尤其是在您根据密钥使用情况优化该索引文件时。(可能甚至在您写入磁盘时也是如此。)
回答by James
A lot of the answers in this thread attempt to overengineer the solution. If I'm correct, you just want to store user settings.
该线程中的许多答案都试图对解决方案进行过度设计。如果我是对的,您只想存储用户设置。
Use an .ini file or App.Config file for this.
为此使用 .ini 文件或 App.Config 文件。
If I'm wrong, and you are storing data that is more than just settings, use a flat text file in csv format. These are fast and easy without the overhead of XML. Folks like to poo poo these since they aren't as elegant, don't scale nicely and don't look as good on a resume, but it might be the best solution for you depending on what you need.
如果我错了,并且您存储的数据不仅仅是设置,请使用 csv 格式的纯文本文件。这些方法既快速又简单,而且没有 XML 的开销。人们喜欢大便,因为它们不那么优雅,不能很好地缩放并且在简历上看起来也不那么好,但根据您的需要,它可能是您的最佳解决方案。