以对象的方式来访问xml数据表(二)

  为什么要以对象的方式来访问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
    }
}
View Code

  后面自己又用xml文件作为数据库开发了一个WPF桌面应用程序和一个小型的网站,此时的动态链接库还没有什么大的改进,只是对其中的代码进行了一些优化。直到那一天,我在用ASP.NET MVC开发工作室的门户网站(此时不再是用xml文件作为数据库,而是用的SQL Sever),涉及到对网站后台数据库的访问时,我发现了Entity Framework访问数据库的方便简洁之处,首先直接在Model里面写一个能够映射一张数据表的类(一般只需包含对应的属性即可),然后使用数据库上下文接口DbContext来轻轻松松访问数据库。先看看代码:

  Model里面的User类:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace Test.Models
{
    public class User
    {
        [Required]
        public Int32 Id { get; set; }

        [Required]
        [DisplayName("名字")]
        public String Name { get; set; }

        [Required]
        [DisplayName("用户名")]
        public String Account { get; set; }

        [Required]
        [DisplayName("密码")]
        public String Password { get; set; }

        //创建时间
        [Required]
        public DateTime CreateTime { get; set; }

        //标识是否为管理员
        [Required]
        public Boolean IsAdmin { get; set; }

    }
}
View Code

  继承了DbContext接口的类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace Test.Models
{
    public class WS_WebAppContext : DbContext
    {

        public virtual DbSet<User> Users { get; set; }

        public WS_WebAppContext() : base("name=WS_WebAppContext")
        {
            
        }
    }
}
View Code

  Control里面轻松访问,只是给出了登录验证部分:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using Test.Models;

namespace Test.Controllers
{
    public class HomeController : Controller
    {
        
        WS_WebAppContext entity = new WS_WebAppContext();
        
         //登录页面
        public ActionResult Login()
        {
            return View();
        }
        
        //检查登录信息
        [HttpPost]
        public ActionResult Login(User u)
        {
            var logined = entity.Users.SingleOrDefault(m => m.Account == u.Account);
            if (!string.IsNullOrWhiteSpace(u.Password) && logined != null && logined.Password == u.Password)
            {
                String role = "User";
                if (logined.IsAdmin)
                {
                    role = "Admin";
                }
                FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                    1,
                    logined.Id.ToString(),
                    DateTime.Now,
                    DateTime.Now.AddMinutes(120),
                    false,
                    role
                   );
                string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
                HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                Response.Cookies.Add(authCookie);
                if (logined.IsAdmin)
                {
                    return RedirectToAction("Index", "Admin");//跳转到管理员的主页
                }
                else
                {
                    return RedirectToAction("Index", "User");//跳转到用户的主页
                }
            }
            else
            {
                return Content("<script>alert('用户名或密码错误!');local.href='/Home/Index'</script>");
            }
        }
    }
}
View Code

  HomeController里面的entity对象就是专门用来访问数据库的,通过它可以简单方便的对数据库里面的数据表(entity.Users就对应着数据库中的用户表)进行增删查改。

当我看到它的简洁方便之处时,灵感来了,我就在想,为什么我不用这种以对象的方式来实现那个专门用于访问xml数据文件的动态链接库呢?

  对于为什么要以对象的方式来访问xml数据表就简单介绍到这里,关键是你要动手去开发过,你才知道这种方式的简洁方便之处。

  让我们在(三)中接着详谈怎样以对象的方式来访问xml数据表。

原文地址:https://www.cnblogs.com/forcheng/p/5329635.html