我首先要说的是,在几个项目的过程中,我以两种不同的方式实现了这一点,但从未对结果感到满意。
注:我知道
不
对使用ORMS感兴趣!
背景
我曾参与过许多项目,这些项目需要为多个平台提供数据库抽象层。在传统的ASP/VBScript时代,我们有一组函数封装SQL文本来清理数据,然后构建适合提供者的字符串(SQL Server、MSSQL、Oracle、DB2等)。
几年前,我写了一个DAL,用实际对象替换了所有复杂的字符串。这个想法很简单,您从一个抽象的数据库类派生了一个数据库类,根据.NET提供程序处理事物的打开/关闭和执行。还有一个
Insert
,
Select
,
Update
对象,这些对象也适用于提供程序。说实话,尽管它可以工作,而且软件可以通过对象与任何数据库一起工作,程序员也不必接触SQL;它很难操作。引入一个新的数据库平台需要时间来创建所有对象。
示例代码:
DB.Database db = DatabasePool.Get();
try
{
DB.Select select = db.NewSelect("_people"); // MSSQL/Oracle/DB2, doesn't matter
select.Add("_id");
select.Add("_people_name");
select.Where.AndClause("_people_name", DB.Operator.Like, "bob");
DB.Results results = select.ExecuteToCollection();
// here, Select is "tailored" to the right DB provider and returns the correct
// sql.
}
finally
{
DatabasePool.Release();
}
下一次迭代对此做了一些改进。不是有一个抽象的数据库类和一大堆表示操作的抽象对象,而是有一组
混凝土
物体。然后,提供程序为每种类型提供一个委托。将对象转换为SQL是一个简单的例子
Dictionary<Type, Delegate>
而且提供程序知道如何将该特定对象(或者实际上是整型)转换为SQL,同时执行数据清理。一切都很好,我改进了对象的访问器:
DB.Database db = DatabasePool.Get();
try
{
DB.Select select = new Select(db); // now a sealed, concrete object
select.Add("_id").Add("_people_name");
select.Where.And("_people_name", DB.Op.Like, "bob");
DB.Results results = select.Query();
// much better now. Select is a sealed object. The Database class has a bunch of
// delegates that convert any type (including Select, Delete, int, decimal) to
// appropriate SQL. Much less work implementing different providers.
}
finally
{
DatabasePool.Release();
}
现在
我现在有机会再做一次(项目时间到了)。我想我的问题是,这是处理将数据库操作封装在对象中的不同提供者的好方法吗?当代表们工作良好时:
1) 很容易为
Column
,
选择
,
Delete
,
int
,
NULL
,等等,但是在构造
WHERE
从句,我最后得到了一堆微小的原子物体,它们做了一些“部分”的事情。
2) 虽然不同风格的SQL有细微的差异,但大多数都是相同的。基本数据库类为几乎所有对象提供了可接受的默认值,不同的提供程序只是替换了这些委托。但我不认为这对程序员来说很“清楚”。目前还不清楚哪些是由哪一层代码处理的。
有更好的办法吗?我很高兴
概念
替换任何SQL语句的对象。它们使动态构建SQL语句变得非常容易,可以清除数据库类型并将其适当地转换为.NET类型(例如,我从不处理数据库对象之外的数据库类型)。我总是得到一个日期时间,System.UInt32,bool等等)。