轻量级灵活的数据持久性选项

时间:2009-05-16 00:32:03

标签: c# persistence

我最初使用SQLCE首先从LINQ to SQL开始,然后转移到Entity Framework,但似乎SQLCE太不灵活了。 (现在我甚至不能删除一个表来重新创建它,因为它说我无法删除PrimaryKeyA,因为它被PrimaryKeyA引用...所以我没有太大的信心可以在以后修改它)< / p>

我需要灵活性,因为应用程序将在多次迭代中发布,数据需要能够相当容易地进行更改。较新版本的应用程序需要能够直接或通过转换从旧版本中读取数据。

部署需要轻量级,低于10MB,但最好低于5.用户将(应该)不修改应用程序外的数据,他们不需要知道或关心数据的存储方式。

高性能不是问题,它只是一个用户的数据。现在我很想说使用XML来利用LINQ to XML。但我想知道是否还有其他建议。我想要一些易于在普通对象之间进行翻译的东西,XML序列化是否适用于此?

我想我正在寻找的是一种简单的方法来保存可以轻松更新为具有对象更改的新版本的对象。性能不是一个大问题,但它应该至少可以容忍少量/中等数量的数据。 (基本上是单个用户食谱的电子形式的烹饪书)

3 个答案:

答案 0 :(得分:2)

总是对文件进行二进制序列化。它不性感,但它有效,并且它不需要任何第三方工具或软件。只需确保在每个数据分组之前加上版本号(通常称为架构编号)。当您更改数据模型时,这将减轻您的头痛。

在OOP设置中,通常每个需要持久化的对象都有一个Serialize()方法,它接受一个方向参数(保存与加载)和一个表示二进制文件的对象。在写出时,您只需要确保每个对象都被序列化。在阅读时,您需要随时创建对象。知道如何将对象输入和输出序列化的容器通常会使这个过程变得更容易。

转换由各种Serialize()方法动态处理。例如,如果当前在Schema版本5上的对象遇到使用Schema版本4编写的数据,它将知道如何处理该数据。

但是,如果您需要像查询功能这样的SQL,这可能不是您的最佳选择。当您要读入所有数据时,这种方法效果最佳。

示例:

假设你有一个类Foo,它有2个你想序列化的成员变量:

class Foo
{
public:
  const unsigned int SCHEMA = 1;
  int i;
  double d;

  void Serialize(bool bSaving, CBinaryFile file)
  {
    if (bSaving)
    {
      // Serialize everything out
      file << SCHEMA << i << d;
    }
    else
    {
      // Read in the schema number first
      unsigned int nSchema;
      file >> nSchema;

      // Validate the schema number
      if (nSchema > SCHEMA)
      {
        // We're reading in data that was written with a newer version of the program
        // Since we don't know how to handle that let's error out
        throw exception;
      }

      // Read everything in
      file >> i >> d;
    }
  }
}

现在让我们说一年你向Foo添加另一个成员。你会像这样处理它:

class Foo
{
public:
  const unsigned int SCHEMA = 2;
  int i;
  double d;
  string s;

  void Serialize(bool bSaving, CBinaryFile file)
  {
    if (bSaving)
    {
      // Serialize everything out
      file << SCHEMA << i << d << s;
    }
    else
    {
      // Read in the schema number first
      unsigned int nSchema;
      file >> nSchema;

      // Validate the schema number
      if (nSchema > SCHEMA)
      {
        // We're reading in data that was written with a newer version of the program
        // Since we don't know how to handle that let's error out
        throw exception;
      }

      // Read everything in
      file >> i >> d;
      if (nSchema > 1)
        file >> s;
    }
  }
}

只要您将所有内容包装在Schema数字中,就可以直接转换。

答案 1 :(得分:2)

我建议使用System.Data.SQLite。它通过ADO.net接口为您提供简单,高性能的SQL,并且轻量级。它也有相当好的文档记录,并且易于使用命令行sqlite.exe客户端和其他工具进行故障排除。 SQLite的一个重要优点是它的打字相对宽松,所以你不必花太多时间搞乱架构。

我不能说它是否支持LINQ,但它非常好。

答案 2 :(得分:1)

我建议你考虑的XML路线可能是一个合理的想法。虽然比二进制序列化更冗长,但如果需要,它更容易调试;如果需要更少的磁盘使用,则可以很好地(即时)压缩。