DataContractSerializer,将T的序列化附加到List <t>的序列化

时间:2018-09-24 08:04:18

标签: 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>中定义,当对数据的内存视图的更改要持久保存到文件时可以调用。

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?

1 个答案:

答案 0 :(得分:3)

像xml这样的格式根本无济于事,并且没有标准的xml序列化程序支持您要执行的操作。

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

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

message SomeRoot {
    repeated SomeType items = 1;
}

然后,只需在现有文件的末尾附加一个 second 列表(包含零个,一个或多个项目),就可以合并两个列表(一个在磁盘上,一个在内存中);所以;具有5个SomeRoot项目的SomeType和简单地附加有3个SomeRoot项目的SomeType与具有8个{{ {1}}个项目。