小菜鸟一步步打造图书馆外挂之四:数据访问(一)
该系统数据量不大,正常情况下不到十条记录,再加上一些用户的配置,所以用XML文件来存储信息比较方便,以后也可能不会放到数据库中,所以在设计数据访问时没有什么设计,只是提供一些增删改的方法。
在解决方案LibraryHelper中添加工程DAL,添加一个类BookXML,对保存图书信息的XML文件的操作。把命名空间改为Libraryhelper.DAL,引入上一小节建好的Model工程。
创建名为BookXML.xml的XML文件用来保存从图书馆网站上读取下来的数据,结构如下:
<?xml version="1.0" standalone="yes"?>
<Books>
<book>
<title>重构:改善既有代码的设计</title>
<borrowDate>2008-12-21</borrowDate>
<returnDate>2009-03-23</returnDate>
<borrowNum>0 续借 </borrowNum>
<isbnNum>TP311.11/31</isbnNum>
</book>
<book>
<title>框架设计:CLR VIA C#</title>
<borrowDate>2008-12-21</borrowDate>
<returnDate>2009-03-23</returnDate>
<borrowNum>0 续借 </borrowNum>
<isbnNum>TP312C/330</isbnNum>
</book>
</Books>
分别保存了书名,外借时间,应还时间,续借次数,图书ISBN编号等信息。把该文件放到本工程的\bin\Debug目录下,读取时不用写路径,而且项目打包时比较方便,整个项目就放在一个文件夹里。
现在来写BookXML类中的方法,该类中有一个对象是用来对XML文件的操作的,可以用DataSet,但是这种做法用一个不好,就是当文件中没有记录时就出错,必须要保持至少有一条记录,如下:
1DataSet bookDataSet;
2public BookXML()
3{
4 bookDataSet = new DataSet();
5 bookDataSet.ReadXml("BookXML.xml");
6}
7
8//取得所有对象
9public List<Book> GetBookList()
10{
11 List<Book> bookList = new List<Book>();
12 Int32 bookNum = bookDataSet.Tables["book"].Rows.Count;
13 for (Int32 i = 0; i < bookNum; i++)
14 {
15 //
16 }
17 //
18}
19
如上代码当没有记录时到第12行就出错,因为当XML文件中没有记录时是这样的:
<Books>
</Books>
没有book标签,所以它还对book的引用就出错,所以采用DOM解析,这种方法操作XML文件很方便,如下,我们写了一些增删改方法:
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Data;
5using System.Collections;
6using System.Xml;
7
8using LibraryHelper.Model;
9
10
11namespace LibraryHelper.DAL
12{
13 public class BookXML
14 {
15 XmlDocument xmlDoc;
16 XmlNode xmlNode;
17
18 public BookXML()
19 {
20 xmlDoc = new XmlDocument();
21 xmlDoc.Load("BookXML.xml"); //加载XML文件
22 xmlNode = xmlDoc.SelectSingleNode("Books");
23 }
24
25 //添加
26 public Boolean InsertBook(Book insertBook)
27 {
28 try
29 {
30 XmlElement xmlNodeBook = xmlDoc.CreateElement("book"); //创建一个标签
31
32 XmlElement xmlNodeTitle = xmlDoc.CreateElement("title");//创建一个标签
33 xmlNodeTitle.InnerText = insertBook.Title;//设置标签的值
34 xmlNodeBook.AppendChild(xmlNodeTitle);//把该标签加到它的父标签中
35
36 XmlElement xmlNodeBorrowDate = xmlDoc.CreateElement("borrowDate");//同上
37 xmlNodeBorrowDate.InnerText = insertBook.BorrowDate.ToShortDateString();
38 xmlNodeBook.AppendChild(xmlNodeBorrowDate);
39
40 XmlElement xmlNodeReturnDate = xmlDoc.CreateElement("returnDate");
41 xmlNodeReturnDate.InnerText = insertBook.ReturnDate.ToShortDateString();
42 xmlNodeBook.AppendChild(xmlNodeReturnDate);
43
44 XmlElement xmlNodeBorrowNum = xmlDoc.CreateElement("borrowNum");
45 xmlNodeBorrowNum.InnerText = insertBook.BorrowNum;
46 xmlNodeBook.AppendChild(xmlNodeBorrowNum);
47
48 XmlElement xmlNodeIsbn = xmlDoc.CreateElement("isbn");
49 xmlNodeIsbn.InnerText = insertBook.ISBN;
50 xmlNodeBook.AppendChild(xmlNodeIsbn);
51
52 xmlNode.AppendChild(xmlNodeBook);
53
54 xmlDoc.Save("BookXML.xml");
55
56 return true;
57 }
58 catch (Exception ex)
59 {
60 throw ex;
61 }
62 }
63
64 //取得所有对象
65 public List<Book> GetBookList()
66 {
67 List<Book> bookList = new List<Book>();
68 for (Int32 i = 0; i < xmlNode.ChildNodes.Count; i++)
69 {
70 Book book = new Book();
71 book.Title = xmlNode.ChildNodes[i].ChildNodes[0].InnerText;
72 book.BorrowDate = Convert.ToDateTime(xmlNode.ChildNodes[i].ChildNodes[1].InnerText);
73 book.ReturnDate = Convert.ToDateTime(xmlNode.ChildNodes[i].ChildNodes[2].InnerText);
74 book.BorrowNum = xmlNode.ChildNodes[i].ChildNodes[3].InnerText;
75 book.ISBN = xmlNode.ChildNodes[i].ChildNodes[4].InnerText;
76 bookList.Add(book);
77 }
78 return bookList;
79 }
80
81 //取得记录数量
82 public Int32 GetBookNum()
83 {
84 return xmlNode.ChildNodes.Count;
85 }
86
87 //取得一条记录
88 public Book GetSingleBookByRowIndex(Int32 rowIndex)
89 {
90 Book book = new Book();
91 book.Title = xmlNode.ChildNodes[rowIndex].ChildNodes[0].InnerText;
92 book.BorrowDate = Convert.ToDateTime(xmlNode.ChildNodes[rowIndex].ChildNodes[1].InnerText);
93 book.ReturnDate = Convert.ToDateTime(xmlNode.ChildNodes[rowIndex].ChildNodes[2].InnerText);
94 book.BorrowNum = xmlNode.ChildNodes[rowIndex].ChildNodes[3].InnerText;
95 book.ISBN = xmlNode.ChildNodes[rowIndex].ChildNodes[4].InnerText;
96 return book;
97 }
98
99 //删除一条记录
100 public Boolean DeleteBookByRowIndex(Int32 rowIndex)
101 {
102 try
103 {
104 xmlNode.RemoveChild(xmlNode.ChildNodes[rowIndex]);
105 xmlDoc.Save("BookXML.xml");
106 return true;
107 }
108 catch (Exception ex)
109 {
110 throw ex;
111 }
112 }
113
114 //删除所有记录
115 public Boolean DeleteAllBook()
116 {
117 try
118 {
119 xmlNode.RemoveAll();
120 xmlDoc.Save("BookXML.xml");
121 return true;
122 }
123 catch (Exception ex)
124 {
125 throw ex;
126 }
127 }
128
129 //修改
130 public Boolean UpdataBookByRowIndex(Int32 rowIndex,Book updateBook)
131 {
132 try
133 {
134 XmlNode updateNode = xmlNode.ChildNodes[rowIndex];
135 updateNode.ChildNodes[0].InnerText = updateBook.Title;
136 updateNode.ChildNodes[1].InnerText = updateBook.BorrowDate.ToShortDateString();
137 updateNode.ChildNodes[2].InnerText = updateBook.ReturnDate.ToShortDateString();
138 updateNode.ChildNodes[3].InnerText = updateBook.BorrowNum;
139 updateNode.ChildNodes[4].InnerText = updateBook.ISBN;
140
141 xmlDoc.Save("BookXML.xml");
142
143 return true;
144 }
145 catch (Exception ex)
146 {
147 throw ex;
148 }
149 }
150 }
151}
152
我们再建一个UserXML的类,把它的命名空间也改成LibraryHelper.DAL,再建一个UserXML.xml的文件,保存用户登录到图书馆的账号和密码,一样放到bin\Debug目录下,在UserXML类里也写了些简单的方法对UserXML.xml文件的操作,如下:
UserXML.xml:
<?xml version="1.0" encoding="utf-8"?>
<Users>
<User>
<LoginName>20050632540</LoginName>
<Password>850313</Password>
</User>
</Users>
UserXML类:
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Xml;
5using LibraryHelper.Model;
6
7namespace LibraryHelper.DAL
8{
9 public class UserXML
10 {
11 XmlDocument xmlDoc;
12 XmlNode xmlNode;
13
14 public UserXML()
15 {
16 xmlDoc = new XmlDocument();
17 xmlDoc.Load("UserXML.xml"); //加载
18 xmlNode = xmlDoc.SelectSingleNode("Users");
19 }
20
21 //取得User
22 public User GetUser()
23 {
24 User user = new User();
25 user.LoginID = xmlNode.ChildNodes[0].ChildNodes[0].InnerText;
26 user.Password = xmlNode.ChildNodes[0].ChildNodes[1].InnerText;
27 return user;
28 }
29
30 //保存
31 public Boolean SaveUser(User user)
32 {
33 try
34 {
35 xmlNode.ChildNodes[0].ChildNodes[0].InnerText = user.LoginID;
36 xmlNode.ChildNodes[0].ChildNodes[1].InnerText = user.Password;
37 xmlDoc.Save("UserXML.xml");
38 return true;
39 }
40 catch (Exception ex)
41 {
42 throw ex;
43 }
44 }
45
46 }
47}
48
依次再加一个对宽带连接账号信息的xml文件和对该文件操作的类如下:
ADSLXML.xml:
<?xml version="1.0" encoding="utf-8"?>
<ADSL>
<ConnectionName>宽带</ConnectionName>
<UserName>user@xyw</UserName>
<UserPassword>user</UserPassword>
</ADSL>
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Xml;
5
6namespace LibraryHelper.DAL
7{
8 public class ADSLXML
9 {
10 XmlDocument xmlDoc;
11 XmlNode xmlNode;
12
13 public ADSLXML()
14 {
15 xmlDoc = new XmlDocument();
16 xmlDoc.Load("ADSLXML.xml"); //加载
17 xmlNode = xmlDoc.SelectSingleNode("ADSL");
18 }
19
20 //返回用户指定的宽带连接名
21 public String GetConnectionName()
22 {
23 return xmlNode.ChildNodes[0].InnerText;
24 }
25
26 //返回用户名
27 public String GetUserName()
28 {
29 return xmlNode.ChildNodes[1].InnerText;
30 }
31
32 //返回密码
33 public String GetUserPassword()
34 {
35 return xmlNode.ChildNodes[2].InnerText;
36 }
37
38 //保存
39 public Boolean SaveADSL(String connectionName, String userName, String userPassword)
40 {
41 try
42 {
43 xmlNode.ChildNodes[0].InnerText = connectionName;
44 xmlNode.ChildNodes[1].InnerText = userName;
45 xmlNode.ChildNodes[2].InnerText = userPassword;
46 xmlDoc.Save("ADSLXML.xml");
47 return true;
48 }
49 catch (Exception ex)
50 {
51 throw ex;
52 }
53 }
54 }
55}
56
同样再那一个xml文件用来保存用户的一些配置信息和对该文件操作的类如下:
SettingXML.xml:
<?xml version="1.0" encoding="utf-8"?>
<Setting>
<warningDay>100</warningDay>
<startType>0</startType>
<lastStartTime>2009-3-6</lastStartTime>
<disConnectionADSL>0</disConnectionADSL>
</Setting>
warningDay是说当还剩n天还书时,当n<100时该书就进入警戒范围,用户开机时就给出提示
startType是说系统每次计算机启动时都启动还是每天只启动一次,0为每次都启动,1为每天只能启动一次,所以下面lastStartTime就保存了上一次的登录时间
disConnectionADSL是说当退出该系统时是否自动断开宽带连接,0为断开,1为不断开
对该文件操作的类SettingXML中的一些方法如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace LibraryHelper.DAL
{
public class SettingXML
{
XmlDocument xmlDoc;
XmlNode xmlNode;
public SettingXML()
{
xmlDoc = new XmlDocument();
xmlDoc.Load("SettingXML.xml");
xmlNode = xmlDoc.SelectSingleNode("Setting");
}
//取得进入警戒时间
public String GetWarningDay()
{
return xmlNode.ChildNodes[0].InnerText;
}
//取得启动类型
public String GetStartType()
{
return xmlNode.ChildNodes[1].InnerText;
}
//取得上次启动时间
public String GetLastStartTime()
{
return xmlNode.ChildNodes[2].InnerText;
}
//取得是否断开宽带连接
public String GetDisconnectionADSL()
{
return xmlNode.ChildNodes[3].InnerText;
}
//该设置可能是分开来设置的,所以方法也分开
//设置进入警戒时间
public void SetWarningDay(String warningDay)
{
try
{
xmlNode.ChildNodes[0].InnerText = warningDay;
xmlDoc.Save("SettingXML.xml");
}
catch (Exception ex)
{
throw ex;
}
}
//设置启动类型
public void SetStartType(String startType)
{
try
{
xmlNode.ChildNodes[1].InnerText = startType;
xmlDoc.Save("SettingXML.xml");
}
catch (Exception ex)
{
throw ex;
}
}
//设置上次启动时间
public void SetLastStartTime(String lastStartTime)
{
try
{
xmlNode.ChildNodes[2].InnerText = lastStartTime;
xmlDoc.Save("SettingXML.xml");
}
catch (Exception ex)
{
throw ex;
}
}
//设置是否断开宽带连接
public Boolean SetDisconnectionADSL(String isConnection)
{
try
{
xmlNode.ChildNodes[3].InnerText = isConnection;
xmlDoc.Save("SettingXML.xml");
return true;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
注意到对ADSLXML.xml和SettingXML.xml文件的操作时我们并没有封装到对象,而是用方法每个属性都分开来取,是因为这些可能在不同一个地方使用,这样单个写用得更方便.