Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dotNET: added page for nested table support #6226

Merged
merged 5 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion product_docs/docs/net_connector/8.0.5.1/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
---
title: "EDB .NET Connector"
directoryDefaults:
description: "EDB .NET Connector version 8.0.2.1 documentation and release notes."
description: "EDB .NET Connector version 8.0.5.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
178 changes: 178 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,178 @@
---
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 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 nested table rows into a `List<object>` in C# while maintaining and converting each column's underlying type. For example, a `[text1, text2, num1]` row will be resolved as a `[string, string, decimal]` item in the list.

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

- If the nested type `IS TABLE OF` a record or composite type **not mapped** to a C# class, all rows become a nested List 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 rows will be `MyComposite` instances.
gvasquezvargas marked this conversation as resolved.
Show resolved Hide resolved

## Example: Retrieving nested table output parameter

This program:

- Creates a package with a nested `emp_tbl_typ` table type of `emp_rec_typ`. This package 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.

!!!note
Always provide type names in lowercase.
!!!

### Program example

Create an empty console program and paste the following code.

```csharp
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
gvasquezvargas marked this conversation as resolved.
Show resolved Hide resolved
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
```
Loading