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