Skip to content

Commit

Permalink
dotNET: added page for nested table support
Browse files Browse the repository at this point in the history
  • Loading branch information
gvasquezvargas committed Nov 11, 2024
1 parent 511b8db commit a33f6ad
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 0 deletions.
20 changes: 20 additions & 0 deletions product_docs/docs/net_connector/8.0.5.1/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@
title: "EDB .NET Connector"
directoryDefaults:
description: "EDB .NET Connector version 8.0.2.1 documentation and release notes."
navigation:
- 01_release_notes
- 02_requirements_overview
- 03_the_advanced_server_net_connector_overview
- 04_installing_and_configuring_the_net_connector
- 05_using_the_net_connector
- 06_opening_a_database_connection
- 07_retrieving_database_records
- 08_parameterized_queries
- 09_inserting_records_in_a_database
- 10_deleting_records_in_a_database
- 11_using_spl_stored_procedures_in_your_net_application
- 12_using_advanced_queueing
- 13_using_a_ref_cursor_in_a_net_application
- 14_using_plugins
- 15_using_object_types
- using_nested_table_types
- 16_scram_compatibility
- 17_advanced_server_net_connector_logging
- 18_api_reference
---

The EDB .NET Connector distributed with EDB Postgres Advanced Server provides connectivity between a .NET client application and an EDB Postgres Advanced Server database server. You can:
Expand Down
176 changes: 176 additions & 0 deletions product_docs/docs/net_connector/8.0.5.1/using_nested_table_types.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
---
title: "Using nested tables"

---

EDB Postgres Advanced Server supports nested table collection types created with `CREATE TYPE ... AS TABLE OF` statements. The EDB .NET Connector supports output parameters declared as nested tables out of the box, whether they are free-standing types or declared inside packages.

## Nested table types mapping

Nested table types are mapped to `List<object>`s in C#, as it is preferred over `ArrayList`. These lists contain as many elements as the nested table type’s rows. The nested table items are translated to be compatible with the C# application using the following rules:

- The connector resolves all elements of a nested table into `List<object>` elements of a single object type, making the element types are consistent in C#.

- If the nested type `IS TABLE OF` a domain type (int, varchar, decimal, etc.): all the elements will be their C# counterpart according to the [Supported Types and their Mappings](https://www.npgsql.org/doc/types/basic.html#read-mappings).

- If the nested type `IS TABLE OF` a record or composite type **not mapped** to a C# class: all elements will be a `List<object>` containing as many elements as the record or composite fields, with proper type translation.

- If the nested type `IS TABLE OF` a record or composite type **mapped** to a C# class (for example, `MyComposite`): all elements will be `MyComposite` instances.

## Example: Retrieving nested table output parameter

This program:

- Creates a package with a nested `emp_tbl_typ` table type of `emp_rec_typ`. This packages has a stored procedure that fills the nested table output parameter.

- Maps the nested table type to a C# class via `MapComposite<>`.

- Executes and displays the results.

Create an empty console program and paste the following code.

!!!note
Always provide type names in lower case.
!!!

```text
internal static class Program
{
const string ConnectionString = "your_connection_string";
// Composite type, will be mapped to the nested table type
// This will work if field types are convertible from database types
public class Employee
{
[PgName("empno")]
public decimal Number;
[PgName("ename")]
public string? Name;
}
public static void Sample_NestedTableTypes(string ConnectionString)
{
var dataSourceBuilder = new EDBDataSourceBuilder(ConnectionString);
dataSourceBuilder.MapComposite<Employee>("pkgextendtest.emp_rec_typ");
using (var dataSource = dataSourceBuilder.Build())
{
using (var connection = dataSource.OpenConnection())
{
try
{
CreatePackage(connection);
var commandText = "pkgExtendTest.nestedTableExtendTest";
var cstmt = new EDBCommand(commandText, connection);
cstmt.CommandType = CommandType.StoredProcedure;
var tableOfParam = cstmt.Parameters.Add(new EDBParameter()
{
Direction = ParameterDirection.Output,
DataTypeName = "pkgextendtest.emp_tbl_typ"
});
cstmt.Prepare();
cstmt.ExecuteNonQuery();
List<object>? employees = tableOfParam.Value as List<object>;
if (employees == null)
{
Console.WriteLine($"No employee found");
return;
}
foreach (var employeeRecord in employees)
{
var employee = employeeRecord as Employee;
if (employee != null)
{
Console.WriteLine($"Employee {employee.Number}: {employee.Name}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
Cleanup(connection);
}
}
}
}
// helper methods to create package and cleaning up
static void CreatePackage(EDBConnection connection)
{
var createPackage =
" CREATE OR REPLACE PACKAGE pkgExtendTest IS \n" +
" TYPE emp_rec_typ IS RECORD ( \n" +
" empno NUMBER(4), \n" +
" ename VARCHAR2(10) \n" +
" ); \n" +
" TYPE emp_tbl_typ IS TABLE OF emp_rec_typ; \n" +
" PROCEDURE nestedTableExtendTest(emp_tbl OUT emp_tbl_typ); \n" +
" END pkgExtendTest; \n";
using (var com = new EDBCommand(createPackage, connection) { CommandType = CommandType.Text })
{
com.ExecuteNonQuery();
}
var createPackageBody =
" CREATE OR REPLACE PACKAGE BODY pkgExtendTest IS \n" +
" PROCEDURE nestedTableExtendTest(emp_tbl OUT emp_tbl_typ) IS \n" +
" DECLARE \n" +
" CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10 order by empno; \n" +
" i INTEGER := 0; \n" +
" BEGIN \n" +
" emp_tbl := emp_tbl_typ(); \n" +
" FOR r_emp IN emp_cur LOOP \n" +
" i := i + 1; \n" +
" emp_tbl.EXTEND; \n" +
" emp_tbl(i) := r_emp; \n" +
" END LOOP; \n" +
" END nestedTableExtendTest; \n" +
" END pkgExtendTest; \n";
using (var com = new EDBCommand(createPackageBody, connection) { CommandType = CommandType.Text })
{
com.ExecuteNonQuery();
}
connection.ReloadTypes();
}
static void Cleanup(EDBConnection connection)
{
var dropPackageBody = "DROP PACKAGE BODY pkgExtendTest";
var dropPackage = "DROP PACKAGE pkgExtendTest";
using (var com = new EDBCommand(dropPackageBody, connection) { CommandType = CommandType.Text })
{
com.ExecuteNonQuery();
}
using (var com = new EDBCommand(dropPackage, connection) { CommandType = CommandType.Text })
{
com.ExecuteNonQuery();
}
}
}
```

The output should look like this:

```text
Employee 7499: ALLEN
Employee 7521: WARD
Employee 7566: JONES
Employee 7654: MARTIN
Employee 7698: BLAKE
Employee 7782: CLARK
Employee 7788: SCOTT
Employee 7839: KING
Employee 7844: TURNER
Employee 7876: ADAMS
```

0 comments on commit a33f6ad

Please sign in to comment.