代码之家  ›  专栏  ›  技术社区  ›  Moo-Juice

在数据库抽象层上查找指针

  •  0
  • Moo-Juice  · 技术社区  · 15 年前

    我首先要说的是,在几个项目的过程中,我以两种不同的方式实现了这一点,但从未对结果感到满意。

    注:我知道 对使用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等等)。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Dan Bryant    15 年前

    你玩过LINQ to SQL吗?它并不是一个功能齐全的ORM,但它确实代表了一个表示数据库操作的流畅模型。即使您不想使用LINQ to SQL,您也可以考虑编写自己的LINQ提供程序,这更符合您的口味。这有一个优势,即已经熟悉LINQ的开发人员可以使用您的系统,而无需额外的学习曲线。如果你还不熟悉,请继续阅读 Expression Trees . LINQ的设计与您所描述的完全一样,并且大量的工作被允许实现非常灵活和自然的查询表示。