例1
表数据入口是Windows 中常用的数据库访问形式,本例演示C#实现。但必须强调一点,这种经典的表数据入口形式不太适合NET环境,因为不能利用ADO.NET数据集的优点。相反,该入口使用数据阅读器IDataReader,(类似于JDBC中的ResultSet,每次从数据库读取一条记录到内存中)。当操作大量信息但又不想一次把全部信息都调入内存,数据阅读器是合适的选择。
使用PersonGateway类来连接数据库中的人员数据表。PersonGateWay包含查询方法的代码,由返回的ADO.NET阅读器访问返回的数据:
//以下为NET代码,且省略一部分工具代码
class PersonGateway{
public IDataReader FindAll() {
String sql = "SELECT * FROM person";
return new SqlCommand(sql, DB.Connection).ExecuteReader();
}
public IDataReader FindAll() {
String sql = "SELECT * FROM person WHERE lastname=?";
SqlDataReader comm = new SqlCommand(sql, DB.Connection).ExecuteReader();
comm.Parameters.Add(new SqlParameter("lastname", lastName));
return comm.ExecuteReader();
}
public IDataReader FindWhere(String whereClause) {
String sql = String.Format("SELECT * FROM person WHERE {0}", whereClause);
return new SqlCommand(sql, DB.Connection).ExecuteReader();
}
}
通常,我们都希望同一个阅读器读取多个行。但少数情况,为了获取单行而使用包含这么多行代码的方法。
下面是我们获取单行记录,而在PersonGateway表入口中写的方法:
class PersonGateway{
...
public Object[] FindAll(long Key) {
String sql = "SELECT * FROM person WHERE id = ?";
SqlCommand comm = new SqlCommand(sql, DB.Connection);
comm.Parameters.Add(new SqlParameter("key", key));
IDataReader reader = comm.ExecuteReader();
reader.Read();
Object[] result = new Object[reader.FieldCount];
reader.GetValues(result);
reader.Close();
return result;
}
}
修改和插入方法从参数接受所需数据并调用相应的SQL例程:
class PersonGateway {
...
public void Update(long key,String lastname, String firstname, long numberOfDepedents) {
String sql = "UPDATE person SET lastname=?,firstname=?,numberOfDependents=? WHERE id=?";
SqlCommand comm = new SqlCommand(sql, DB.Connection);
comm.Parameters.Add(new SqlParameter("key", key));
comm.Parameters.Add(new SqlParameter("lastname", lastname));
comm.Parameters.Add(new SqlParameter("firstname", firstname));
comm.Parameters.Add(new SqlParameter("numberOfDependents", numberOfDependents));
comm.ExecuteNonQuery();
}
}
class PersonGateway {
...
public long Insert(String lastname, String firstname, long numberOfDepedents) {
String sql = "INSERT INTO person VALUES (?,?,?,?)";
long key = GetNextID();
SqlCommand comm = new SqlCommand(sql, DB.Connection);
comm.Parameters.Add(new SqlParameter("key", key));
comm.Parameters.Add(new SqlParameter("lastname", lastname));
comm.Parameters.Add(new SqlParameter("firstname", firstname));
comm.Parameters.Add(new SqlParameter("numberOfDependents", numberOfDependents));
return key;
}
}
表入口的删除指定记录行操作:
class PersonGateway {
...
public void Delete(long key ) {
String sql = "DELETE FROM person WHERE id=?";
SqlCommand comm = new SqlCommand(sql, DB.Connection);
comm.Parameters.Add(new SqlParameter("key", key));
comm.ExecuteNonQuery();
}
}
例2 JDBC 版本的表数据入口
这里我们使用了一个简单的表数据入口来封装SQL查询。我在以前说过,对于事务脚本,业务逻辑简单。所以表数据入口对于很简单的数据逻辑而言,可以灵活的把每个表对应一个入口,改变成一个入口对应多个表。
因此,此例中只使用一个入口,而不是为每个表设立一个单独的入口。
class Gateway {
private db;
public ResultSet findRecognitionFor(long contractID, MfDate asof) {
String sql = "SELECT amount FROM revenueRecognitions WHERE contract=? AND recognition<=?";
PreparedStatement stmt = db.prepareStatement(sql);
stmt.setLong(1, contractID);
stmt.setLong(2, asof.toSqlDate());
ResultSet result = stmt.executeQuery();
return result;
}
}
以下为合同的查找器方法:
class Gateway {
public ResultSet findContract(long contractID) {
String sql = "SELECT * FROM revenueRecognitions WHERE contract=? AND recognition<=?";
PreparedStatement stmt = db.prepareStatement(sql);
stmt.setLong(1, contractID);
stmt.setLong(2, asof.toSqlDate());
ResultSet result = stmt.executeQuery();
return result;
}
}
以下是对数据库插入操作的封装:
class Gateway {
public void insertRecognition(long contractID,Money amount,MfDate asof) {
String sql = "INSERT INTO revenueRecognitions VALUES (?,?,?)";
PreparedStatement stmt = db.prepareStatement(sql);
stmt.setLong(1, contractID);
stmt.setBigDecimal(2, amount.amount());
stmt.setDate(3, asof.toSqlDate());
stmt.executeUpdate();
}
}