为了学习,我试图抽象化数据库访问,希望能够仅插入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?
答案 0 :(得分:3)
像xml这样的格式根本无济于事,并且没有标准的xml序列化程序支持您要执行的操作。
为避免数据丢失的风险,您可以加载现有数据,添加新对象,将序列化到其他文件,然后交换(重命名)文件。
还有其他更易于追加的格式。例如,protobuf不会终止root元素,因此如果您收到以下形式的消息:
message SomeRoot {
repeated SomeType items = 1;
}
然后,只需在现有文件的末尾附加一个 second 列表(包含零个,一个或多个项目),就可以合并两个列表(一个在磁盘上,一个在内存中);所以;具有5个SomeRoot
项目的SomeType
和简单地附加有3个SomeRoot
项目的SomeType
与具有8个{{ {1}}个项目。