OracleDataAdapter 作为 DataSet 和数据库之间的桥梁,用于检索和保存数据。OracleDataAdapter 这个桥梁通过这样的方法提供:使用 Fill 将数据从数据库加载到 DataSet 中,使用 Update 将在 DataSet 中所作的更改发送回数据源。
当 OracleDataAdapter 填充 DataSet 时,它为返回的数据创建必需的表和列(如果它们尚不存在)。但是,除非 MissingSchemaAction 属性设置为 AddWithKey,否则这个隐式创建的架构中不包括主键信息。也可以使用 FillSchema,让 OracleDataAdapter 创建 DataSet 的架构,并在用数据填充它之前就将主键信息包括进去。有关更多信息,请参见向数据集添加现有约束 (ADO.NET)。
OracleDataAdapter 还包括 SelectCommand、InsertCommand、DeleteCommand、UpdateCommand 和 TableMappings 属性,以便于数据的加载和更新。
用于 Oracle 的 .NET Framework 数据提供程序不支持批处理 SQL 语句。但是,它确实允许您使用多个 REF CURSOR 输出参数来填充 DataSet,每个参数都位于它自己的 DataTable 中。您必须对参数进行定义,将它们标记为输出参数,并指示它们是 REF CURSOR 数据类型。注意,使用存储过程返回的 REF CURSOR 填充 OracleDataAdapter 时,您不能使用 Update 方法,因为在执行 SQL 语句时,Oracle 不提供确定表名称和列名称所需的信息。下面的 C# 示例假定您已创建了此存储过程。
在 Oracle 服务器上创建下面的 Oracle 包。
CREATE OR REPLACE PACKAGE CURSPKG AS
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE OPEN_ONE_CURSOR (N_EMPNO IN NUMBER,
IO_CURSOR OUT T_CURSOR);
PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
DEPTCURSOR OUT T_CURSOR);
END CURSPKG;
/
在 Oracle 服务器上创建下面的 Oracle 包正文。
CREATE OR REPLACE PACKAGE BODY CURSPKG AS
PROCEDURE OPEN_ONE_CURSOR (N_EMPNO IN NUMBER,
IO_CURSOR OUT T_CURSOR)
IS
V_CURSOR T_CURSOR;
BEGIN
IF N_EMPNO <> 0 THEN
OPEN V_CURSOR FOR
SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND EMP.EMPNO = N_EMPNO;
ELSE
OPEN V_CURSOR FOR
SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;
END IF;
IO_CURSOR := V_CURSOR;
END OPEN_ONE_CURSOR;
PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
DEPTCURSOR OUT T_CURSOR)
IS
V_CURSOR1 T_CURSOR;
V_CURSOR2 T_CURSOR;
BEGIN
OPEN V_CURSOR1 FOR SELECT * FROM EMP;
OPEN V_CURSOR2 FOR SELECT * FROM DEPT;
EMPCURSOR := V_CURSOR1;
DEPTCURSOR := V_CURSOR2;
END OPEN_TWO_CURSORS;
END CURSPKG;
/
以下 C# 示例阐释如何使用存储过程获取表和列信息。
// GetConnectionString() returns a connection string for
// the data source.
string connString = GetConnectionString();
DataSet ds = new DataSet();
OracleConnection conn = new OracleConnection(connString);
OracleCommand cmd = conn.CreateCommand();
cmd.CommandText = "CURSPKG.OPEN_TWO_CURSORS";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("EMPCURSOR", OracleType.Cursor).Direction =
ParameterDirection.Output;
cmd.Parameters.Add("DEPTCURSOR", OracleType.Cursor).Direction =
ParameterDirection.Output;
OracleDataAdapter da = new OracleDataAdapter(cmd);
da.TableMappings.Add("Table", "Emp");
da.TableMappings.Add("Table1", "Dept");
da.Fill(ds);
ds.Relations.Add("EmpDept", ds.Tables["Dept"].Columns["Deptno"],
ds.Tables["Emp"].Columns["Deptno"], false);
下面的 Visual Basic 示例阐释了如何通过 OracleDataAdapter 利用 Oracle REF CURSOR 来填充 DataSet。这些示例使用 Oracle Scott/Tiger 架构中定义的表,并且需要下面的 PL/SQL 包和包正文。必须在您的服务器上创建这些包和包正文才能使用这些示例。
在 Oracle 服务器上创建下面的 Oracle 包。
CREATE OR REPLACE PACKAGE CURSPKG AS
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE OPEN_ONE_CURSOR (N_EMPNO IN NUMBER,
IO_CURSOR OUT T_CURSOR);
PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
DEPTCURSOR OUT T_CURSOR);
END CURSPKG;
/
在 Oracle 服务器上创建下面的 Oracle 包正文。
CREATE OR REPLACE PACKAGE BODY CURSPKG AS
PROCEDURE OPEN_ONE_CURSOR (N_EMPNO IN NUMBER,
IO_CURSOR OUT T_CURSOR)
IS
V_CURSOR T_CURSOR;
BEGIN
IF N_EMPNO <> 0 THEN
OPEN V_CURSOR FOR
SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND EMP.EMPNO = N_EMPNO;
ELSE
OPEN V_CURSOR FOR
SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;
END IF;
IO_CURSOR := V_CURSOR;
END OPEN_ONE_CURSOR;
PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,
DEPTCURSOR OUT T_CURSOR)
IS
V_CURSOR1 T_CURSOR;
V_CURSOR2 T_CURSOR;
BEGIN
OPEN V_CURSOR1 FOR SELECT * FROM EMP;
OPEN V_CURSOR2 FOR SELECT * FROM DEPT;
EMPCURSOR := V_CURSOR1;
DEPTCURSOR := V_CURSOR2;
END OPEN_TWO_CURSORS;
END CURSPKG;
/
此 Visual Basic 示例执行一个返回两个 REF CURSOR 参数的 PL/SQL 存储过程,然后使用返回的行填充 DataSet。
' GetConnectionString() returns a connection string for
' the data source.
Dim connString As New String(GetConnectionString())
Dim ds As New DataSet()
Dim conn As New OracleConnection(connString)
Dim cmd As OracleCommand = conn.CreateCommand()
cmd.CommandText = "CURSPKG.OPEN_TWO_CURSORS"
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("EMPCURSOR", OracleType.Cursor).Direction = _
ParameterDirection.Output
cmd.Parameters.Add("DEPTCURSOR", OracleType.Cursor).Direction = _
ParameterDirection.Output
Dim da As New OracleDataAdapter(cmd)
da.TableMappings.Add("Table", "Emp")
da.TableMappings.Add("Table1", "Dept")
da.Fill(ds)
ds.Relations.Add("EmpDept", ds.Tables("Dept").Columns("Deptno"), _
ds.Tables("Emp").Columns("Deptno"), False)
使用 OracleDataAdapter 执行 Fill 或 FillSchema 操作之后,不管列是否能够更新,DataColumn.ReadOnly 属性始终返回假,因为 Oracle 服务器不返回此信息。