LINQ非常牛逼,操作数据库和集合对象非常方便,已经得到了非常广泛的应用。好处我不多说了。今天来给大家看看LINQ对XML的增删改查操作,并且封装为DAL类,方便在多层结构的应用程序中使用。以我网站的友情链接模块为例:
XML文件的结构如下:
1 XNA Develop http://www.xnadevelop.com/ 1 2 BlogNT 开源.NET博客 http://www.blognt.com/ 2
和以往写ORM一样,我们首先要把对数据的描述抽象为model:
public sealed class FriendLink { private int _id; private string _title; private string _url; private int _orderId; public int Id { get { return _id; } set { _id = value; } } public string Title { get { return _title; } set { _title = value; } } public string Url { get { return _url; } set { _url = value; } } public int OrderId { get { return _orderId; } set { _orderId = value; } } }
接下来我们就可以用LINQ 写DAL了。
注意先要using这些命名空间:
using System.Linq; using System.Xml; using System.Xml.Linq;
下面代码中的_xmlPath局部变量是你XML文件的虚拟路径。
Add(新增一条记录):
public bool Add(GeekStudio.ORM.Model.FriendLink model) { try { int id = GetNextId(); string path = HttpContext.Current.Server.MapPath(_xmlPath); XDocument xDoc = XDocument.Load(path); xDoc.Element(rootName).Add( new XElement("FriendLink", new XElement("Id", id), new XElement("Title", model.Title), new XElement("Url", model.Url), new XElement("OrderId", model.OrderId) )); xDoc.Save(path); return true; } catch { return false; } }
GetModel(查询:根据Id获取一条记录(一个Model))
public GeekStudio.ORM.Model.FriendLink GetModel(int Id) { string path = HttpContext.Current.Server.MapPath(_xmlPath); XDocument xDoc = XDocument.Load(path); var q = from fdlink in xDoc.Descendants("FriendLink") where fdlink.Element("Id").Value == Id.ToString() select new ORM.Model.FriendLink() { Id = Convert.ToInt32(fdlink.Element("Id").Value), Title = fdlink.Element("Title").Value, Url = fdlink.Element("Url").Value, OrderId = Convert.ToInt32(fdlink.Element("OrderId").Value) }; return q.ToList()[0]; }
如果要返回一个Model List集合,只要把写成return q.ToList()就可以了。
Delete(删除一条记录)
public bool Delete(int Id) { try { string path = HttpContext.Current.Server.MapPath(_xmlPath); XDocument xDoc = XDocument.Load(path); (from fdlink in xDoc.Descendants("FriendLink") where fdlink.Element("Id").Value == Id.ToString() select fdlink).Remove(); xDoc.Save(path); return true; } catch { return false; } }
Update(更新一条记录)
public bool Update(GeekStudio.ORM.Model.FriendLink model) { try { string path = HttpContext.Current.Server.MapPath(_xmlPath); XDocument xDoc = XDocument.Load(path); var q = from fdlink in xDoc.Descendants("FriendLink") where fdlink.Element("Id").Value == model.Id.ToString() select fdlink; foreach (XElement xe in q) { xe.SetElementValue("Title", model.Title); xe.SetElementValue("Url", model.Url); xe.SetElementValue("OrderId", model.OrderId); } xDoc.Save(path); return true; } catch { return false; } }
至此,我们已经写好了CRUD的4个方法。大家可以根据自己需要做调整。
附:生成下一个Id的方法(寻找最大的Id然后+1)
private static int GetNextId() { string path = HttpContext.Current.Server.MapPath(_xmlPath); try { XDocument xDoc = XDocument.Load(path); var q = (from fdlink in xDoc.Descendants("FriendLink") select fdlink.Element("Id").Value).Max(); int i = int.Parse(q); return i + 1; } catch { return 0; } }
提示:这个方法是有bug的。文末公布bug。
不过XML做数据库还是无法和传统的关系型数据库做比较,毕竟思想不一样。比如这个方法。我们知道,通过最大ID+1生成的新Id是可笑的。我们的本意是Id为IDENTITY列。但如果让数据库做,这个Id就不会是最大Id+1了。比如你有一坨记录,Id为1,2,3,4。你把4删了,再增加一条记录,数据库绝对不会把新记录的Id写成4。而是从5开始的。
另外,XML也有很多硬伤,无法和数据库相比。本文只是演示如何用LINQ对XML进行增删改查操作,并不是建议大家用XML做数据库。至于用什么来存数据,这是一个“适合和不适合”的命题,而不是一个“对与错”的命题~。
刚才提到的bug其实是这样的:
select Convert.ToInt32(fdlink.Element("Id").Value)).Max();
恍然大悟吧?:D