# Tipi Custom Database

Questa cartella contiene la documentazione di tutti i 10 tipi custom del database (esclusi i tipi PLJSON).

## Tipi per Funzioni Pipelined

Questi tipi sono utilizzati dalle funzioni che ritornano tabelle (pipelined functions).

### F_GET_OSPITI

| Tipo | Descrizione |
|------|-------------|
| [T_DET_OSPITI_ROW](T_DET_OSPITI_ROW.md) | Tipo OBJECT per singola riga |
| [T_DET_OSPITI_TAB](T_DET_OSPITI_TAB.md) | Tipo TABLE OF T_DET_OSPITI_ROW |

```sql
-- Struttura T_DET_OSPITI_ROW
CREATE TYPE T_DET_OSPITI_ROW AS OBJECT (
    ID_EVENTO      NUMBER,
    TOT_ADULTI     NUMBER,
    TOT_KINDER     NUMBER,
    TOT_BABY       NUMBER,
    TOT_STAFF      NUMBER,
    TOT_INVITATI   NUMBER,
    NOTE_ADULTI    VARCHAR2(1000),
    NOTE_KINDER    VARCHAR2(1000),
    NOTE_BABY      VARCHAR2(1000),
    NOTE_STAFF     VARCHAR2(1000)
);

-- Struttura T_DET_OSPITI_TAB
CREATE TYPE T_DET_OSPITI_TAB AS TABLE OF T_DET_OSPITI_ROW;
```

### F_REP_ALLESTIMENTI

| Tipo | Descrizione |
|------|-------------|
| [T_REP_ALLESTIMENTI_ROW](T_REP_ALLESTIMENTI_ROW.md) | Tipo OBJECT per singola riga |
| [T_REP_ALLESTIMENTI_TAB](T_REP_ALLESTIMENTI_TAB.md) | Tipo TABLE OF T_REP_ALLESTIMENTI_ROW |

### F_REP_CUCINA

| Tipo | Descrizione |
|------|-------------|
| [T_REP_CUCINA_ROW](T_REP_CUCINA_ROW.md) | Tipo OBJECT per singola riga |
| [T_REP_CUCINA_TAB](T_REP_CUCINA_TAB.md) | Tipo TABLE OF T_REP_CUCINA_ROW |

## Tipi Utility

| Tipo | Descrizione |
|------|-------------|
| [STRING_LIST](STRING_LIST.md) | Tipo TABLE OF VARCHAR2 per liste stringhe |
| [ENUM_TABLE_OBJECT](ENUM_TABLE_OBJECT.md) | Tipo OBJECT per STRING_TO_TABLE_ENUM |
| [ENUM_TABLE_TYPE](ENUM_TABLE_TYPE.md) | Tipo TABLE OF ENUM_TABLE_OBJECT |
| [XLIB_VC2_ARRAY_T](XLIB_VC2_ARRAY_T.md) | Array di VARCHAR2 per XLIB |

## Utilizzo in Query

```sql
-- Esempio uso F_GET_OSPITI
SELECT * FROM TABLE(F_GET_OSPITI(123));

-- Esempio uso STRING_TO_TABLE_ENUM
SELECT * FROM TABLE(STRING_TO_TABLE_ENUM('A:B:C', 0, ':'));
```

## Migrazione .NET

In .NET i tipi Oracle pipelined vengono sostituiti con classi DTO e IEnumerable/IAsyncEnumerable.

### Esempio T_DET_OSPITI_ROW → DTO

```csharp
public class DettaglioOspitiDto
{
    public int IdEvento { get; set; }
    public int TotAdulti { get; set; }
    public int TotKinder { get; set; }
    public int TotBaby { get; set; }
    public int TotStaff { get; set; }
    public int TotInvitati { get; set; }
    public string NoteAdulti { get; set; }
    public string NoteKinder { get; set; }
    public string NoteBaby { get; set; }
    public string NoteStaff { get; set; }
}
```

### Esempio F_GET_OSPITI → Metodo Service

```csharp
public async Task<DettaglioOspitiDto> GetOspitiAsync(int idEvento)
{
    var ospiti = await _context.EventiDetOspiti
        .Where(o => o.IdEvento == idEvento)
        .ToListAsync();

    return new DettaglioOspitiDto
    {
        IdEvento = idEvento,
        TotAdulti = ospiti.FirstOrDefault(o => o.CodTipoOspite == "8")?.Numero ?? 0,
        TotKinder = ospiti.FirstOrDefault(o => o.CodTipoOspite == "5")?.Numero ?? 0,
        TotBaby = ospiti.FirstOrDefault(o => o.CodTipoOspite == "6")?.Numero ?? 0,
        TotStaff = ospiti.FirstOrDefault(o => o.CodTipoOspite == "7")?.Numero ?? 0,
        TotInvitati = ospiti.Sum(o => o.Numero ?? 0),
        NoteAdulti = ospiti.FirstOrDefault(o => o.CodTipoOspite == "8")?.Note,
        NoteKinder = ospiti.FirstOrDefault(o => o.CodTipoOspite == "5")?.Note,
        NoteBaby = ospiti.FirstOrDefault(o => o.CodTipoOspite == "6")?.Note,
        NoteStaff = ospiti.FirstOrDefault(o => o.CodTipoOspite == "7")?.Note
    };
}
```

### Esempio STRING_TO_TABLE_ENUM → Extension Method

```csharp
public static class StringExtensions
{
    public static IEnumerable<string> ToTableEnum(this string input, char delimiter = ':')
    {
        if (string.IsNullOrEmpty(input))
            yield break;
            
        foreach (var item in input.Split(delimiter))
        {
            yield return item.Trim();
        }
    }
}

// Uso
var items = "A:B:C".ToTableEnum(':');
```
