为什么要以对象的方式来访问xml数据表?
还记得,自己是在一次完成师兄布置的任务时接触到了xml,那时候需要用xml来作为数据文件,保存一个简单的图书管理系统的数据。于是就知道了,可以用xml文件来保存数据(而且比用简单的文本文件保存数据规范的多,在访问与读取数据上面都十分方便),就这样使用xml的征程开始了。
自己做的第一个WPF桌面应用程序——备忘录,就是用xml文件作为数据库。而且那个时候考虑到以后可能会经常使用到xml文件作为数据库,于是乎就写了一个专门用于访问xml文件的动态链接库,这样不仅可以提高代码的重用性(用功一次,获益无穷),而且还提高了软件后期的维护效率(由于规范),动态链接库实现的基本功能:将连接数据文件的过程和检查规范全封装在一个方法里面(而数据表的属性是通过数组传参传递),将对数据的增、删、查、改也全部封装成各种方法,还封装了一些属性等等。但此时的自己还没有面向对象开发的思维,最终在开发时还是以传统的方式去访问的xml数据表(Element(value))。
这是我第一个版本的访问xml的动态链接库源码:
using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using System.IO; using System.Text.RegularExpressions; namespace XmlIDataBase { public class XmlDataBase { #region 私有字段 private string xmlFilePath; private string[] xmlProperties; private string noteName; #endregion #region 公有字段 public XElement Notes; #endregion #region 公有方法 //连接数据文件 public bool Connect(string path_, string noteName_, params string[] properties) { try { //匹配xml文件路径 if (!Regex.IsMatch(path_, @"^(?<fpath>([a-zA-Z]:\\)([\s\.\-\w]+\\)*)(?<fname>[\w]+.[\w]+)") || noteName_ == "" || path_.Length < 5 || path_.Substring(path_.Length - 3).ToLower() != "xml") { return false; } noteName = noteName_;//记录每条记录的名称 xmlFilePath = path_;//记录文件路径 if (path_.LastIndexOf("\\") > 0) { path_ = path_.Substring(0, path_.LastIndexOf("\\")); } else { path_ = ""; } if (path_ != "" && !Directory.Exists(path_)) { Directory.CreateDirectory(path_); var xmlFile = new StreamWriter(xmlFilePath); xmlFile.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); xmlFile.WriteLine("<" + noteName + "s>"); xmlFile.WriteLine("</" + noteName + "s>"); xmlFile.Close(); } else { if (!File.Exists(xmlFilePath)) { var xmlFile = new StreamWriter(xmlFilePath); xmlFile.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); xmlFile.WriteLine("<" + noteName + "s>"); xmlFile.WriteLine("</" + noteName + "s>"); xmlFile.Close(); } } Notes = XElement.Load(xmlFilePath); xmlProperties = new string[properties.Length]; xmlProperties = properties;//记录每条记录的属性 return true; } catch (Exception e) { throw e; //return false; } } //保存数据文件 public bool SaveChanged() { try { Notes.Save(xmlFilePath); return true; } catch (Exception e) { throw e; //return false; } } //添加纪录:添加到末尾(方法一) public bool AddNote(params string[] propertyValues) { try { if (propertyValues.Length == xmlProperties.Length) { if (Notes.Elements(noteName).Count() > 0) { int newNo; var lastNote = from Note in Notes.Elements() select Convert.ToInt32(Note.Attribute("No").Value); newNo = lastNote.Max() + 1; Notes.LastNode.AddAfterSelf(noteName, new XAttribute("No", newNo)); for (int i = 0; i < xmlProperties.Length; i++) { if (i == 0) { Notes.Elements().Last().AddFirst(new XElement(xmlProperties[i], propertyValues[i])); } else { Notes.Elements().Last().LastNode.AddAfterSelf(new XElement(xmlProperties[i], propertyValues[i])); } } } else { Notes.AddFirst(new XElement(noteName, new XAttribute("No", 1))); for (int i = 0; i < xmlProperties.Length; i++) { if (i == 0) { Notes.Element(noteName).AddFirst(new XElement(xmlProperties[i], propertyValues[i])); } else { Notes.Element(noteName).LastNode.AddAfterSelf(new XElement(xmlProperties[i], propertyValues[i])); } } } return true; } else { return false; } } catch (Exception e) { throw e; //return false; } } //添加记录:添加到末尾(方法二) public bool AddNote(XElement newNote) { try { if (newNote.Elements().Count() == xmlProperties.Length) { if (Notes.Elements(noteName).Count() > 0) { int newNo; var lastNote = from Note in Notes.Elements() select Convert.ToInt32(Note.Attribute("No").Value); newNo = lastNote.Max() + 1; if(newNote.Attribute("No") == null) { newNote.Add(new XAttribute("No", newNo)); } else { newNote.Attribute("No").Value = newNo.ToString(); } Notes.Elements().Last().AddAfterSelf(newNote); } else { if (newNote.Attribute("No") == null) { newNote.Add(new XAttribute("No", 1)); } else { newNote.Attribute("No").Value = "1"; } Notes.AddFirst(newNote); } return true; } else { return false; } } catch (Exception e) { throw e; //return false; } } //添加记录:添加到开头 public bool AddFistNote(XElement newNote) { try { if (newNote.Elements().Count() == xmlProperties.Length) { if (Notes.Elements(noteName).Count() > 0) { int newNo; var lastNote = from Note in Notes.Elements() select Convert.ToInt32(Note.Attribute("No").Value); newNo = lastNote.Max() + 1; if (newNote.Attribute("No") == null) { newNote.Add(new XAttribute("No", newNo)); } else { newNote.Attribute("No").Value = newNo.ToString(); } Notes.AddFirst(newNote); } else { if (newNote.Attribute("No") == null) { newNote.Add(new XAttribute("No", 1)); } else { newNote.Attribute("No").Value = "1"; } Notes.AddFirst(newNote); } return true; } else { return false; } } catch (Exception e) { throw e; //return false; } } //删除记录(单一索引) public bool DeletNote(string no = "", params string[] propertyValues) { try { bool okFlag = false; if (propertyValues.Length > xmlProperties.Length) { return false; } else { if (no == "") //按属性值相等删除 { for (int i = 0; i < propertyValues.Length; i++) { if (propertyValues[i] == "") continue; if (Notes.Elements(noteName).Count() == 0) return false;//数据文件内容为空 var proNotes = Notes.Elements(noteName).Elements(xmlProperties[i]).Where(m => m.Value == propertyValues[i]); foreach (var item in proNotes) { item.Parent.Remove(); okFlag = true; } } } else //按编号相等删除 { if (Notes.Elements(noteName).Count() == 0) return false;//数据文件内容为空 var proNote = Notes.Elements(noteName).SingleOrDefault(m => m.Attribute("No").Value == no); if (proNote != null) { proNote.Remove(); okFlag = true; } } return okFlag; } } catch (Exception e) { throw e; //return false; } } //修改记录(编号索引:方法一) public bool ModifyNote(string no, params string[] propertyValues) { try { if (no == "" || propertyValues.Length != xmlProperties.Length) { return false; } bool okFlag = false; if (Notes.Elements(noteName).Count() == 0) return false;//数据文件内容为空 var proNote = Notes.Elements(noteName).Attributes("No").SingleOrDefault(m => m.Value == no); if (proNote != null) { var proSubNotes = proNote.Parent.Elements(); int i = 0; foreach (var item in proSubNotes) { item.Value = propertyValues[i++]; } okFlag = true; } return okFlag; } catch (Exception e) { throw e; //return false; } } //修改记录(编号索引:方法二用一个新的节点(No值不变)替代) public bool ModifyNote(string no, XElement noteModified) { try { if (no == "" || noteModified.Elements().Count() != xmlProperties.Length) { return false; } bool okFlag = false; if (Notes.Elements(noteName).Count() == 0) return false;//数据文件内容为空 var proNote = Notes.Elements(noteName).Attributes("No").SingleOrDefault(m => m.Value == no); if (proNote != null) { proNote.Parent.ReplaceWith(noteModified); } return okFlag; } catch (Exception e) { throw e; //return false; } } //查询记录(单一索引) public IEnumerable<XElement> QueryNote(string no = "", params string[] propertyValues) { IEnumerable<XElement> result = null; try { if (no == "" && propertyValues.Length == 0)//返回所有数据 { return Notes.Elements(noteName); } if (no == "" && propertyValues.Length != 0) { for (int i = 0; i < propertyValues.Length; i++) { if (propertyValues[i] == "") continue; if (Notes.Elements(noteName).Count() == 0) return result;//数据文件内容为空 var proNotes = Notes.Elements(noteName).Elements(xmlProperties[i]).Where(m => m.Value == propertyValues[i]); return proNotes; } } else { if (Notes.Elements(noteName).Count() == 0) return result;//数据文件内容为空 var proNote = Notes.Elements(noteName).Attributes("No").SingleOrDefault(m => m.Value == no); if (proNote != null) { result = new XElement[] { proNote.Parent }; } } return result; } catch (Exception e) { throw e; //return false; } } //获取记录的条数 public int Count() { try { return Notes.Elements(noteName).Count(); } catch (Exception e) { throw e; //return false; } } //获取所有记录 public IEnumerable<XElement> AllNotes() { try { return Notes.Elements(noteName); } catch (Exception e) { throw e; //return false; } } //获取最后一条记录的No public int GetLastNoteNo() { try { if (Notes.Elements(noteName).Count() > 0) return (from Note in Notes.Elements(noteName) select Convert.ToInt32(Note.Attribute("No").Value)).Max(); else return 0; } catch (Exception e) { throw e; //return false; } } #endregion } }