使用 LINQ 简化的基于 XML 的电话簿数据库
使用 LINQ 简化的基于 XML 的电话簿数据库。
引言
有一天,我一直在思考 ADO .NET 如何利用数据集和 ORM 工具来实现数据库访问。XML 技术强大的功能给我留下了深刻的印象。使用纯 XML,我们可以利用关系数据库的几乎所有功能(感谢它的发明者)。XML 的引入改变了程序的构建方式、配置文件结构等。在 .NET 中,dataset
类可以将其临时数据读写到 XML 中。当我想使用这些功能开发一个小应用程序时,我考虑使用 ORM 操作来开发这个应用程序。
在搜索数据集到对象的表映射时,我发现该框架无法像 LINQ to SQL 那样工作。所以最后我决定开发自己的应用程序,该应用程序将对象映射到数据集数据,反之亦然,并最终将数据持久化到 XML 文件中。
在这个应用程序中,我想分享一些关于我使用 XML 作为数据库后端,并使用 LINQ 在数据集上进行数据表到对象映射的应用程序的信息。
背景
正如我在介绍中所说,我一直在寻找通过 XML 从数据集进行数据持久化的方法。虽然我找到了很多代码片段,但我发现使用 LINQ 操作数据集进行数据操作非常简单强大,我想在这里分享。
概念
应用程序的通用功能是存储联系人详细信息并从数据库(在本例中是 XML 文件)检索联系人。该应用程序采用分层架构设计,分为三个层次,各层之间相互分离。
- 数据层,数据持久化到 XML 文件中
- 数据访问层和业务层,在本例中 DAL 和 BL 定义在 DAL 类中,数据从 XML 文件跨数据集映射到联系人对象,同时数据也从活动联系人类通过
Dataset
保存到 XML 中。 - UI 层,数据展示使用任何技术开发,例如 Windows Forms、WPF、Web 等。在本例中,我使用 Windows Forms 作为 UI 层来举例说明。
这里的代码背后的主要概念在于,一旦数据从 XML 文件加载,它就会加载到数据集中,然后数据集中的数据会被映射到相应的联系人对象。与其他 ORM 工具(如 LINQ to SQL)一样,我们是从数据集到对象手动进行映射。之后,一旦对象映射完成,业务功能就使用 LINQ 在对象上进行操作,以执行各种操作。
Using the Code
这里的代码分为两部分——第一部分是设计数据访问层类及其业务层,执行所有操作。第二部分是 UI,它被设计成可以执行电话簿应用程序的各种操作。在我的应用程序中,虽然我只为 UI 层使用了 Windows Form,但它可以轻松地扩展到其他 UI,如 WPF、Web Forms 等。DAL 层包括 contact
类和 dataset
数据读取
ReadData()
方法将数据从 XML 文件读取到 dataset
,然后 dataset
中的数据行被映射到 contact
对象。
//read data from the xml file and
private void ReadData()
{
try
{
ds.Clear();
Contacts.Clear();
//checks whether the file exists otherwise it create blank file
if (!System.IO.File.Exists(FileName))
{
System.IO.File.Create(FileName);
}
else
{//read data to dataset then map the data row to contact object
ds.ReadXml(FileName, XmlReadMode.IgnoreSchema);
Contact c;
foreach (DataRow dr in ds.Tables[0].Rows)
{
c = new Contact() { SN = Convert.ToInt32(dr[0]),
Name = dr[1].ToString(), Tele = dr[2].ToString(),
Email = dr[3].ToString(), Gender = Convert.ToChar(dr[4]) };
//added to the contacts collection
Contacts.Add(c);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//throw (ex);
}
}
关键在于 dataset
用于将数据从 XML 映射到 contact
对象。最后,contacts
集合保存了 contact
对象的数据信息,这样使用 LINQ 查询对象就变得容易了。
业务操作
现在让我们看看其他典型操作,一旦数据加载到 contacts
列表中,例如我们想获取所有 contacts
。
//using simple LINQ operation we can get all the contacts
public List<Contact> GetContact()
{
var cont = (from cc in Contacts
orderby cc.SN
select cc).ToList();
return cont;
}
//for single contact
public Contact GetContact(int id)
{
return Contacts.Where(cc => cc.SN == id).SingleOrDefault();
}
再次看看典型的 CRUD 操作,数据操作也通过简单的操作来维护。但是,与典型的 ADO.NET 数据库应用程序不同,所有操作都只是在列表上进行的。
//to delete contact from the list
public Boolean DeleteContact(int id)
{ //remove the contact with the id from the contacts list
return Contacts.Remove(GetContact(id))?true:false;
}
//to add contact into list
public void AddContact(Contact c)
{
//add the new contact to the Contacts list
Contacts.Add(c);
}
//clear the list
public void clearlist()
{
//clears the contacts from the collection
Contacts.Clear();
}
数据保存
最后,只有当调用 Save()
方法时,Contacts
对象列表才会被持久化到 XML 文件中。这看起来像典型的 LINQ to SQL 操作,数据只在调用 datacontext
对象的 submitchange()
方法时保存到数据库。这里的 save
方法看起来像这样
//maps the object from the contacts list to datarow in the dataset
//the dataset is saved to the xml file
public Boolean Save()
{
try
{
ds.Clear();
DataRow dr;
foreach (Contact c in Contacts)
{
dr = ds.Tables[0].NewRow();
dr[0] = c.SN;
dr[1] = c.Name;
dr[2] = c.Tele;
dr[3] = c.Email;
dr[4] = c.Gender;
ds.Tables[0].Rows.Add(dr);
}
ds.WriteXml(FileName, XmlWriteMode.IgnoreSchema);
return true;
}
catch (Exception ex) {
return false;
}
这里的过程与读取操作相反,数据从对象映射到 datarow,最后数据通过 dataset
对象的 WriteXml()
方法从数据集保存到 XML 文件。最后,该层被编译为类库,供 UI 层引用。
UI 层
由于业务操作层是在 DAL 中完成的,UI 层的主要操作就是呈现数据。主要操作就是引用类库,并在你喜欢的 UI 中实现电话簿应用程序的功能。在本例中,我选择使用 Windows Forms 实现,尽管它也可以以类似的方式扩展到 Web 应用程序和 WPF。

当 Windows Form 加载时,联系人数据会被绑定到 bindingsource
,该 binding source 在整个应用程序中用于绑定窗体上的 Windows 控件和数据网格。
using Book;
//....
private void Form1_Load(object sender, EventArgs e)
{
//gets all contact in object form
bindingSource1.DataSource = dall.GetContact();
bindsource();
bindControls();
}
public void bindsource()
{ dgvaddress.DataSource = bindingSource1;
}
许多 binding source 操作都非常直接。我简单地使用 binding source 的方法,例如
Bindingsource1.MoveFirst()
Bindingsource1.MoveNext()
Bindingsource1.AddNew()
等等。
最后,当数据编辑和操作完成后,我们会调用 DAL 类方法 save
来持久化数据。
private void btnsave_Click(object sender, EventArgs e)
{ //save data in the grid to xml file
AddGridValuetolist();
if (dall.Save())
MessageBox.Show("success");
else
MessageBox.Show("error");
}
当点击保存按钮时,首先将网格中的数据映射到联系人列表,然后将每个联系人添加到 DAL 层类中的 Contacts
列表中,之后,调用 DAL 类的 save
方法将列表数据保存到 XML 文件中。
// adds the datarow from the grid to contact list
public void AddGridValuetolist()
{
Contact c;
dall.clearlist();
foreach (DataGridViewRow dr in dgvaddress.Rows)
{
if (dr.Cells [2].Value != null)
{ //mapping from datagridviewrow into contact object
c = new Contact()
{
SN = Convert.ToInt32(dr.Cells[0].Value),
Name = Convert.ToString(dr.Cells[1].Value),
Tele = Convert.ToString(dr.Cells[2].Value),
Email = Convert.ToString(dr.Cells[3].Value),
Gender = Convert.ToChar(dr.Cells[4].Value)
};
dall.AddContact(c);
}
}
}
看点
正如我详细解释的那样,本文的重点是创建对象到数据集的映射。在这里,我们创建了自己的对象持久化到数据库以及通过 dataset
从 XML 文件到对象的数据映射方式。在这种情况下,如果您熟悉 LINQ to SQL,datacontext
类会创建数据库中的表到对象的映射,反之亦然。在我们的应用程序中,使用 dataset
和 LINQ 查询进行对象到 XML 数据的映射。在开发应用程序时,我的主要目的是开发基于 XML 的数据库。然而,当我查看一些东西时,我找不到任何 ORM 类工具可以与数据集一起工作。LINQ to dataset 仍然为我提供了数据列表操作,就像任何集合一样,带有数据表和数据行,而像 LINQ to SQL 那样的对象映射能力在 LINQ to dataset 中是不可用的。这促使我开发一个基于 ORM 的应用程序,使用 LINQ to Dataset
,最终将其持久化到 XML 文件。
历史
- 2010年11月24日:初始版本