数据库独立访问






4.59/5 (18投票s)
2005年1月5日
3分钟阅读

81180

1081
使用不同的数据库提供程序,而无需将实现绑定到其中一个。
引言
如果您需要将一个使用一个数据库的项目移植到另一个数据库,您就会知道这有多痛苦。通过将所有实现细节隐藏在 DataProvider
中,我们可以通过指定要使用的数据库类型来实现实现独立性。
特点
DataProvider
目前支持 Ole DB 和 SQL Server 提供程序,但您可以轻松地对其进行自定义以支持您希望的提供程序。您可以使用 SQL 参数对数据库执行 SQL 语句,以防止 SQL 注入。 DataProvider
在设计时考虑了连接池,尽管我尚未在生产环境中对其进行测试。使用反射,不再需要编写繁琐的代码来填充类对象。最后,DataProvider
支持非查询 SQL 的数据库事务。
入门
将 DataProvider.cs 复制到您的项目中,并在必要时为您的项目目的重命名命名空间。 使用 DataProvider
很简单,像这样声明它
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
如果要使用 SQL 提供程序,请将 OleDb
更改为 SqlServer
。 将 ConnectionString
更改为您正在使用的数据库。 现在假设我们要返回整个 Test 表中的行数
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
DataSet = dp.ExecuteScalar("SELECT COUNT(*) FROM Test;");
很简单,对吧? 这样会更好。 使用参数化 SQL 对于防止 SQL 注入非常重要。 此外,构建字符串会产生难看的代码。 这是另一个更新数据库的片段
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
DataProvider.Command cmd =
dp.CreateCommand("UPDATE Test SET TestString=@TestString;");
cmd.AddParameter("@TestString", "Test123");
dp.ExecuteNonQuery(cmd);
我避免允许 AddParameter()
指定数据类型。 虽然这可能很有用,但它使得迎合不同提供程序支持的不同数据类型变得异常困难。 所有参数都作为对象添加到命令中。
检索 DataReaders 和 DataSets
那么,如果您需要 DataReader
和 DataSet
提供的强大功能该怎么办? DataProvider
像上面的代码一样轻松地提供这种支持。
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
try
{
using (IDataReader reader = dp.ExecuteReader("SELECT * FROM Test;"))
{
while (reader.Read())
{
for (int i=0; i<reader.FieldCount; i++)
{
Response.Write(reader.GetName(i) + ": " + reader.GetValue(i));
}
}
reader.Close();
}
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine(exception.Message);
}
我在这里使用了 using
关键字来确保销毁 IDataReader
对象,从而确保关闭数据库连接,释放服务器的资源。 IDataReader
对象的使用方式与您一直使用它们的方式相同,因此您应该已经熟悉了这一点。 获取和使用 DataGrid
甚至更容易
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
DataSet = dp.FillDataSet("SELECT * FROM Test;");
请注意,到目前为止我们使用的所有函数都已重载以接受字符串和 Command 对象,因此您可以轻松地在纯 SQL 字符串或参数化 SQL 之间切换。
使用事务
如果没有使用 DataProvider
,使用事务从未如此简单。 只需创建一个命令对象数组,然后将其传递给 ExecuteTransaction()
。 同样,您可以选择使用纯 SQL 或参数化 SQL。
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
DataProvider.Command [] commands = new DataProvider.Command[2];
commands[0] =
dp.CreateCommand("INSERT INTO Test (TestNumber, TestString, TestDate)
VALUES (73, @TestString, @TestDate);");
commands[0].AddParameter("@TestString", "Testing");
commands[0].AddParameter("@TestDate", DateTime.Now);
commands[1] = dp.CreateCommand("UPDATE Test SET TestNumber=44 WHERE ID=2;");
dp.ExecuteTransaction(commands);
使用反射
如果您还不知道,反射允许我们以编程方式访问和修改对象的类信息。 因此,我们可以使用它从数据库表中填充对象。
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
TestObject obj = new TestObject();
obj = (TestObjec) dp.ReflectObject("SELECT * FROM Test WHERE TestID=37;",
obj.GetType());
在这里,TestObject
是一个用户定义的类。 确保类成员变量名称与数据库中的字段名称匹配。 不匹配的字段将被忽略。 我在这里实例化一个新的 TestObject
是因为我需要它来获取其类型。 但是,这是不必要的,因为 ReflectObject()
无论如何都会返回一个新实例。
我尚未找到一种无需实例化(我认为这是运行时识别所必需的)或指定程序集名称即可确定类型的方法。
您还可以使用 DataProvider
来反映对象的多个实例并将其作为 ICollection
返回。
DataProvider dp =
new DataProvider(ConnectionString, DataProvider.DBType.OleDb);
TestObject obj = new TestObject();
List = (ArrayList) dp.ReflectCollection("SELECT * FROM Test;",
obj.GetType());
最终注释
即使您不需要数据库独立访问,DataProvider
也易于使用。 如果您有任何疑问或建议,请发送电子邮件至 me。