65.9K
CodeProject 正在变化。 阅读更多。
Home

适用于 .NET 的后关系数据库入门:Matisse - 第 4 部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (26投票s)

2004年3月15日

4分钟阅读

viewsIcon

167678

使用后关系数据库进行 ADO.NET 编程

引言

这是关于适用于 .NET 的 Matisse 后关系数据库的入门系列文章的第四篇。之前的文章列表如下:

第 4 部分涵盖 ADO.NET 编程。文章从一个简单的示例开始,然后说明如何使用 SQL REF() 函数检索 .NET 对象而不是值,这是使用 Matisse 的优势之一。本文还展示了一个使用 DataGrid 与后关系数据库的简单 GUI 应用程序。

如果您已经熟悉 ADO.NET,那么本文中除了如何使用 SQL REF() 函数直接检索对象而无需任何映射之外,并没有什么真正新的内容。这在下面的“返回对象”部分有解释。

简单示例

为了在本文中描述 ADO.NET 编程,我使用了与前几篇文章相同的模式。

UML Diagram

下一个程序将连接到 Matisse 数据库,执行一个 SQL SELECT 语句,然后检索返回的值。

using System;
using System.Data;
using com.matisse;
using com.matisse.Data;namespace ConsoleApplication1
{
  class ConsoleAppClass1
  {
    [STAThread]
    static void Main(string[] args)
    {
      // Create a connection object using a connection string
      MtDatabase myConn = new MtDatabase(
         "Server=localhost;Database=example");
      myConn.Open(); 
 
      // Create an instance of MtCommand
      IDbCommand myCmd = myConn.CreateCommand(); 
      myCmd.CommandText = "SELECT ProjectName, Budget FROM Project;";
 
      // Execute the SELECT statement. 
      // A read-only transaction started by Matisse
      IDataReader reader = myCmd.ExecuteReader();
      // Read rows
      while ( reader.Read() )
      {
        // Get value for the first and second columns
        string pname   = reader.GetString(0);
        decimal budget = reader.GetDecimal(1);
        Console.WriteLine(pname + ", " + budget);
      }
 
      // Clean up
      reader.Close();
      myCmd.Dispose();
      myConn.Close();
    }
  }
}

以下是关于此程序的一些说明:

Matisse 的 ADO.NET 连接对象由 MtDatabase 类创建,该类的名称与标准的命名约定略有不同。

MtDatabase 类和其他 ADO.NET 相关类定义在 com.matissecom.matisse.Data 命名空间中。

返回对象

上面的程序是最基本的 ADO.NET 示例,您随处可见。尽管它证明了 Matisse 就像关系型产品一样工作,但这对我来说并不是那么令人兴奋。Matisse 一个非常有趣的功能是您可以在 ADO.NET 中检索对象而不进行映射。下一段代码展示了如何做到这一点。

      // Create a connection object using a connection string
      MtDatabase myConn = 
        new MtDatabase("localhost", "example", 
              new MtPackageObjectFactory("MatisseApp,PersistentClasses")); 
      
      myConn.Open();
       
      // Create an instance of MtCommand
      IDbCommand myCmd = myConn.CreateCommand(); 
      myCmd.CommandText = 
        "SELECT REF(p) FROM Project p WHERE p.Budget >= 10000;";   // -- A
 
      // Execute the SELECT statement.
      MtDataReader reader = (MtDataReader) myCmd.ExecuteReader();
      while ( reader.Read() )
      {
        // Get the Project object from the ADO.NET Reader object
        Project prj = (Project) reader.GetObject(0);  // -- B
 
        // Get the manager of the project.
        // This is a navigation through relationship.
        Manager mgr = prj.ManagedBy;  // -- C 
 
        // Get the members of the project
        Employee[] members = prj.Members;  // -- D
        foreach (Employee emp in members) 
        {
          ...
        }
      }

首先,您需要使用代码生成工具(在本系列第 3 部分中有介绍)从数据库模式生成 Project 类,以便直接检索对象。

如上所示,要使用 SQL SELECT 语句检索对象,请在 select 子句(A 行)中使用 REF 函数,并在 ADO.NET DataReader 对象上调用 GetObject 方法(B 行)。

获取 Project 对象后,您可以通过访问 Project 对象的属性来获取项目的经理(C 行)和项目中工作的成员(D 行)。这是使用后关系数据库的另一个优点。它真正简化了数据访问层。

请注意,您需要将 MtPackageObjectFactory 对象传递给 MtDatabase 构造函数,以指定存根类(例如 Manager)的位置,即位于名为 PersistentClasses 的程序集中 MatisseApp 命名空间中。

DataGrid 示例

下一段代码摘自一个使用 DataGrid 显示 SQL 查询结果的程序(参见下图)。同样,这段代码没有什么特别之处,但它证明了 Matisse 提供了一个关系型接口。

    private void button1_Click(object sender, System.EventArgs e)
    {
      MtDatabase myConn = new MtDatabase("localhost", "example");

      myConn.Open(); 

      // Create a DataAdapter 
      MtDataAdapter myCommand = 
        new MtDataAdapter(
          "SELECT ProjectName, Budget, ManagedBy.Name Manager 
                           FROM Project;", myConn);
 
      DataSet ds = new DataSet();
      myCommand.Fill(ds, "Projects");
 
      dataGrid1.SetDataBinding(ds, "Projects");
 
      myConn.Close();
    }

Screenshot of DataGrid Example

调用 SQL 存储方法

您可以使用“StoredProcedure”类型的 ADO.NET 命令对象调用 Matisse SQL 存储方法。或者,您可以使用 CALL 语法调用静态存储方法。例如,假设您定义了下一个存储方法,该方法根据姓名查找 Employee 对象:

CREATE STATIC METHOD FindByName(nameToFind VARCHAR)
RETURNS Employee
FOR Employee
BEGIN
  DECLARE emp Employee;
 
  SELECT REF(e) INTO emp FROM Employee e
   WHERE Name = nameToFind;
 
  RETURN emp;
END;

由于上述方法返回单个对象,您可以使用 ExecuteScalar 方法来执行存储方法。

// Create a command object from a connection object
MtCommand mtcmd = myConn.CreateCommand();
 
// Set the CALL statement to call the stored method
mtcmd.CommandText = "CALL Employee::FindByName('Ken Jupiter');";
 
// Execute the stored method, and get the returned object
Employee emp = (Employee) mtcmd.ExecuteScalar();

Matisse 还有一个有趣的功能,允许您像调用常规 .NET 方法一样调用对象上的 SQL 存储方法(非静态),无需 SQL 语句。我将在下一篇文章中讨论此功能。

总结和下一篇文章

在本文中,我展示了如何将 ADO.NET 与 Matisse 结合使用,特别是如何使用 ADO.NET 返回对象。

在下一篇文章中,我将讨论在 Matisse 的 .NET 编程中使用“Object APIs”,它提供了性能改进以及使用全文索引的能力。

附录:使用 ADO.NET 插入对象

下一段代码等同于上一篇文章中展示的程序,用于通过“Object APIs”插入 EmployeeManagerProject 对象。

    // Create a connection object
    MtDatabase myConn = 
     new MtDatabase("localhost", "example");

    myConn.Open(); 
    IDbTransaction dbtran = myConn.BeginTransaction(); 

    // Create an instance of MtCommand
    IDbCommand myCmd = myConn.CreateCommand(); 

    // Insert an Empoyee #1
    myCmd.CommandText = "INSERT INTO Employee (Name, BirthDate)" +
         "VALUES ('John Venus', DATE '1955-10-01') RETURNING INTO emp1";
    myCmd.ExecuteNonQuery();
 
    // Insert another Employee #2
    myCmd.CommandText = "INSERT INTO Employee (Name, BirthDate)"+ 
        "VALUES ('Amy Mars', DATE '1965-9-25') RETURNING INTO emp2";
    myCmd.ExecuteNonQuery();
 
    // Insert a Manager
    myCmd.CommandText = "INSERT INTO Manager (Name, BirthDate, Title)"+ 
       "VALUES ('Ken Jupiter', DATE '1952-12-15', 'Director')"+
       " RETURNING INTO mgr";
    myCmd.ExecuteNonQuery();
 
    // Insert a Project with the above manager 
    // and two employees as its members
    myCmd.CommandText = 
       "INSERT INTO Project (ProjectName, ManagedBy, Members) "+
        "VALUES ('Whidbey', mgr, SELECTION(emp1, emp2))";
    myCmd.ExecuteNonQuery();

    dbtran.Commit();
    myConn.Close();

<< 上一篇 | 下一篇 >>

历史

  • 2004 年 4 月 27 日:初始版本

许可证

本文没有明确附加许可,但可能包含文章文本或下载文件本身的使用条款。如有疑问,请通过下方的讨论区与作者联系。您可以在此处找到作者可能使用的许可列表。

© . All rights reserved.