【问题标题】:data access layer using xml files使用 xml 文件的数据访问层
【发布时间】:2012-01-18 06:53:59
【问题描述】:

我想创建一个数据访问层,支持 CRUD 方法,并带有 XML 文件的底层存储。
我是 XML 新手,我不太确定如何使用 XmlDocumentXDocumentXmlSerializer 等。
这是我对数据访问类的基本想法:

public class EmployeesDao
    {
        private const string FILE_NAME = "file.xml";

            //an XDocument which contains all the employees records
        private XDocument m_XDocument;
        private XmlSerializer m_XmlSerializer;


        public TestCasesDao()
        {
            //is this correct?
                    m_XDocument = XDocument.Load(@"c:\" + FILE_NAME);
            m_XmlSerializer = new XmlSerializer(typeof(EmployeeDTO));
        }

        public void Save(IEmployee employee)
        {
            var dto = new EmployeeDTO(employee);
            //TODO: serialize the DTO, add it to the XDocument, and save to file
        }

        public IEmployee GetEmployee(string name)
        {
                    //TODO: retrieve an EmployeeDTO from my XDocument
                    return employeeDto.Convert();  //return an IEmployee
        }

            //TODO: update and delete methods...
    }

关于如何填补缺失的空白有什么想法吗?

【问题讨论】:

    标签: c# c#-4.0 xml-serialization


    【解决方案1】:

    对于序列化,您可以使用通用方法

    public static class GenericSerializer
    {
        public static string Serialize<T>(ICollection<T> listToSerialize)
        {
            MemoryStream stream = new MemoryStream();
            XmlSerializer xmlSerializer;
            try
            {
                xmlSerializer = new XmlSerializer(typeof(List<T>));
                xmlSerializer.Serialize(stream, listToSerialize);
    
                return Encoding.UTF8.GetString(stream.ToArray());
            }
            finally
            {
                stream.Close();
            }
        }
    
        public static string Serialize<T>(T objectToSerialize)
        {
            MemoryStream stream = new MemoryStream();
            XmlSerializer xmlSerializer;
            try
            {
                xmlSerializer = new XmlSerializer(typeof(T));
                xmlSerializer.Serialize(stream, objectToSerialize);
                return Encoding.UTF8.GetString(stream.ToArray());
            }
            finally
            {
                stream.Close();
            }
        }
    
      public static T Deserialize<T>(string xmlDataToeSerialize)
        {
            XmlSerializer xmlDeSerializer = new XmlSerializer(typeof(T));
            StringReader stringReader = new StringReader(xmlDataToeSerialize);
            return (T)xmlDeSerializer.Deserialize(stringReader);            
        }
    }
    

    对于更新和删除您可以从文件中检索集合或对象并编辑和覆盖现有的,或者您可以使用 XPath 表达式直接编辑 XML

    XML/0340_XPath.htm">http://www.java2s.com/Tutorial/CSharp/0540_XML/0340_XPath.htm

    【讨论】:

    • 这个可以和XDocument一起使用吗?我宁愿使用 LINQ2XML 而不是 XPath
    • 如果您使用序列化,则不必使用 XDocument。因为它用于编辑原始 xml。即使您想要..您可以使用 XDocument 编辑序列化的 xml 字符串。但它不是编辑序列化字符串的好习惯。
    【解决方案2】:

    这真的取决于您的需求。将 XML 用于 DAL 仅对小型项目有意义,即使在这种情况下,SQLite 也可能是更好的解决方案。 XML 的唯一“好处”是它是一种文本的、人类可读的格式,但从这个意义上说,它作为导出文件的作用比实际的 DAL 技术更好。任何“手工制作”的单文件数据库系统的问题在于,您每次进行更改时都需要保存整个文件(如果您不选择memory mapped files,这可能会根据您的需要过度杀伤)。

    对于每个插入或更新操作,您都需要一个读取器和一个写入器,以便将所有记录复制到一个新文件中。根据您的文件大小,一个选项可能是在您的应用程序生命周期内将记录保留在内存中,并每隔一段时间将它们刷新到磁盘。这将是一个静态可用的列表(考虑到并发性),但只有当数据库相对较小时才有意义。

    您最关心的可能是一致性和事务完整性。如果您有两个进程同时使用同一个 XML 文件,则很难同步访问。此外,应用程序崩溃或电源故障可能会使您的数据损坏,这意味着您还应该考虑某种日志系统。例如,SQLite 乍一看似乎很简单,它是ACID,并付出了很大的努力来实现这一点(如果你有时间,请查看this lengthy article 了解一下)。从头开始实现这一点真的是大材小用。

    因此,总而言之,您的选择是:

    1. 你只有一个进程使用一个文件。

      一个。数据库很小:保存在内存中,锁定所有操作,并定期刷新。比较简单。

      b.数据库很大:

      • 在每次操作时使用读取器/写入器组合复制整个文件。非常简单,但速度较慢。

      • 保留命令队列并分批刷新它们。更快,增加了一些事务支持,但很复杂。

    2. 另一个进程可以访问该文件。

      一个。实施日志机制以防止同时访问。

      b.创建一个单独的服务,它将自己处理所有事务。

    在任何情况下,您都可能需要保留事务日志文件并使用它来确保数据在访问之间保持一致。您的应用程序应该能够自行从故障中恢复。我的观点是 SQLite 可能是要走的路:结合像 NHibernate 这样的 ORM 解决方案,它使用起来非常简单和安全。

    【讨论】:

    • 谢谢。我已经做了上述考虑(应用程序数据集预计非常小,应用程序是单线程的,预计不会出现同步问题)。如您所见,我最初的想法是在内存中保留XDocument(就像您建议的那样)。然而,我的问题更多的是关于技术方法、使用序列化、XDocuments 等
    • @sJhonny:如果您要将其保存在内存中,恕我直言,使用XDocument 毫无意义。只需保留一个对象列表(毕竟您可以使用 LINQ to Objects)并使用普通的XmlSerializer 来加载和保存整个文件。在这种情况下,我认为没有必要以您的数据库技术规定的格式保存您的域数据(这类似于使用数据集,而不是使用实际的 DTO)。每次需要查找对象时都需要遍历 XML 树,使用普通列表(或字典)更简单、更快捷。
    猜你喜欢
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 2011-10-20
    • 2014-10-01
    • 1970-01-01
    相关资源
    最近更新 更多