c# - DataContractSerializer,将 T 的序列化附加到 List<T> 的序列化

标签 c# serialization deserialization

为了学习,我正在尝试抽象出数据库访问,希望能够仅插入 XML 文件或 JSON 文件来提供数据访问。

现在我的类型有以下构造函数

public XmlRepository(XElement root)
{
        _rootElement = root;
        Load();
}

依赖项(根)由 XmlContext 类型提供,如下所示:

private void Load()
    {
        if (!File.Exists(_fileName))
        {
            var schoolsXElement = new XElement("Schools");
            var gradesXElement = new XElement("Grades");
            var teachersXElement = new XElement("Teachers");
            var studentsXElement = new XElement("Students");

            _document = new XDocument(new XElement("DB"));
            _document.Root.Add(schoolsXElement);
            _document.Root.Add(gradesXElement);
            _document.Root.Add(teachersXElement);
            _document.Root.Add(studentsXElement);
            using (var fs = new FileStream(_fileName, FileMode.Create))
            {
                _document.Save(fs);
            }

        }
        else
        {
            _document = XDocument.Load(_fileName);
        }

        Schools = new XmlRepository<School>(_document.Root.Element("Schools"));
        Grades = new XmlRepository<Grade>(_document.Root.Element("Grades"));
        Teachers = new XmlRepository<Teacher>(_document.Root.Element("Teachers"));
        Students = new XmlRepository<Student>(_document.Root.Element("Students"));
    }

这些方法在 XmlRepository<T> 中定义当对数据的内存 View 的更改要保存到文件时可以调用。

private void Load()
    {
        if (!_rootElement.HasElements)
        {
            _persistentStorage = new List<T>();
            _memoryStorage = new List<T>();
            return;
        }

        var xmlDeserializer = new DataContractSerializer(typeof(List<T>));
        var obj = xmlDeserializer.ReadObject(_rootElement.FirstNode.CreateReader()) as List<T>;
        _persistentStorage = new List<T>(obj);
        _memoryStorage = new List<T>(obj);
    }

    private void Save()
    {
        var xmlSerializer = new DataContractSerializer(typeof(List<T>));
        var newAdditions = _memoryStorage.Except(_persistentStorage).ToList();
        _persistentStorage.AddRange(newAdditions);
        _rootElement.RemoveAll();
        using (var fs = _rootElement.CreateWriter())
        {
            xmlSerializer.WriteObject(fs, _persistentStorage);
        }
    }

private void Save()
    {
        var xmlSerializer = new DataContractSerializer(typeof(List<T>));
        var newAdditions = _memoryStorage.Except(_persistentStorage).ToList();
        _persistentStorage.AddRange(newAdditions);
        _rootElement.RemoveAll();
        using (var fs = _rootElement.CreateWriter())
        {
            xmlSerializer.WriteObject(fs, _persistentStorage);
        }
    }

所有这些都呈现以下 XML(来自测试运行)

<?xml version="1.0" encoding="utf-8"?>
<DB>
  <Schools>
    <ArrayOfSchool xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models" />
  </Schools>
  <Grades>
    <ArrayOfClass xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="LearningProject.Models">
      <Class>
        <Id xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models">0</Id>
        <Grade>126368128361</Grade>
        <Students xmlns:d3p1="http://schemas.datacontract.org/2004/07/LearningProject.Models" i:nil="true" />
        <Teacher i:nil="true" />
      </Class>
      <Class>
        <Id xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models">1</Id>
        <Grade>126368128361</Grade>
        <Students xmlns:d3p1="http://schemas.datacontract.org/2004/07/LearningProject.Models" i:nil="true" />
        <Teacher i:nil="true" />
      </Class>
    </ArrayOfClass>
  </Grades>
  <Teachers>
    <ArrayOfTeacher xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models" />
  </Teachers>
  <Students>
    <ArrayOfStudent xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/LearningProject.Models" />
  </Students>
</DB>

现在我的问题是保存方法,我觉得删除那里的任何东西并用持久存储中的任何东西替换它并不舒服。假设我那里有 10K 个元素并且只添加 1 个,我将删除 10K 个元素只是为了能够再添加 1 个。

我将如何改为附加到 XML?

最佳答案

像 xml 这样的格式根本不利于追加,而且没有标准的 xml 序列化程序支持您想要执行的操作。

为避免数据丢失的风险,您或许可以加载现有数据、添加新对象、序列化到不同的文件,然后交换(重命名)文件。

还有其他格式对追加更友好。例如,protobuf 不会终止根元素,因此如果您收到以下形式的消息:

message SomeRoot {
    repeated SomeType items = 1;
}

然后您可以合并两个列表(一个在磁盘上,一个在内存中),只需在现有文件的末尾附加 第二个 列表(包含零个、一个或多个项目);所以;一个包含 5 个 SomeType 项的 SomeRoot 简单地附加一个包含 3 个 SomeType 项的 SomeRoot相同的 到具有 8 个 SomeType 项的 SomeRoot

关于c# - DataContractSerializer,将 T 的序列化附加到 List<T> 的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52474995/

相关文章:

c# 流读取和反序列化

java - 使用java将对象发送到本地主机服务器?

java - 最终 transient 字段的序列化/反序列化

java - 由于 XMI 无法正确加载容器,正在加载序列化的 Ecore 模型

c# - 在 C# 中填充 Azure 表存储表

c# - .NET:从数组中对象的动态属性中检索值

java - Serialized RDD如何在内存中占用更少的空间?

c# - 无法将子字符串发送到数据库

c# - Xamarin Android - 从另一个 Activity 更新一个 Activity 的 UI 控制

c# - XML反序列化iso 20022 pain.001.001.03来自xsd使用c#