https://github.com/0username/simple.dbextensions.tvp
https://github.com/0username/simple.dbextensions.tvp
Last synced: about 1 year ago
JSON representation
- Host: GitHub
- URL: https://github.com/0username/simple.dbextensions.tvp
- Owner: 0UserName
- Created: 2025-02-04T17:21:12.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2025-05-13T19:46:18.000Z (about 1 year ago)
- Last Synced: 2025-05-13T20:58:38.333Z (about 1 year ago)
- Language: C#
- Size: 19.5 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README

# Motivation
The motivation for developing the library is to simplify the creation of `DataTable` instances used as table-valued parameters when interacting with stored procedures, as well as to add a number of additional features, including pooling, schema and data validation, and column trimming.
# Usage
Add a dependency on this package and create a class implementing `ITableValued`, using the built-in `AbstractTableValued` implementation or your own. Once this is done, you can create a `DataTable` based on your class definitions:
```csharp
[TableValued(nameof(Row))]
public class Row : AbstractTableValued
```
```csharp
Row[] rows = new
Row[]
{
new Row(),
new Row(),
new Row()
};
using (PooledDataTableScope scope = rows.BuildScope())
{
Upload(scope.Table);
}
```
Or
```csharp
PooledDataTable table = rows.Build();
Upload(table);
table.Return();
```
Or
```csharp
PooledDataTable table = new Row().Build();
Upload(table);
table.Return();
```
If you are using [Dapper](https://github.com/DapperLib/Dapper), add:
```csharp
SqlMapper.AddTypeMap(typeof(PooledDataTable), DbType.Object);
```
## Pooling
Pooling is applied at each stage of creating a `DataTable` (but not for `DataRow`). Each type has its own pool, which has a fixed size of 50. If needed, a different configuration can be specified:
```csharp
[TableValuedPool(10)]
public class Row : AbstractTableValued
```
## Metadata
In the simplest case, to create a `DataTable`, only information about the columns is needed: name, type, and ordinal. By default, this information is retrieved using reflection. Everything is presented in a static form, except for `Ordinal`, which can be overridden:
```csharp
[TableValued(nameof(Row))]
public class Row : AbstractTableValued
{
[Ordinal(1)]
public int Property0
[Ordinal(0)]
public int Property1
}
```
However, it is also possible to load custom metadata from a database, which have a higher priority:
```csharp
MetadataStorage.AddColumns(nameof(Row), new IColumnExternalMetadata[]
{
new ColumnExternalMetadata(table: nameof(Row), name: nameof(Row.Property0), type: typeof(int).FullName, ordinal: 1, allowDBNull: default, maxLength: -1, unique: default),
new ColumnExternalMetadata(table: nameof(Row), name: nameof(Row.Property1), type: typeof(int).FullName, ordinal: 0, allowDBNull: default, maxLength: -1, unique: default)
});
```
`AllowDBNull`, `MaxLength`, and `Unique` are built-in constraints that are checked after all rows have been loaded into the `DataTable`. If any of these constraints are violated, a `ConstraintException` or `NoNullAllowedException` will be thrown.
> **NOTE**: If a property is not part of a table-valued parameter, it will be discarded. However, when the structure in the database is changed after the metadata has been loaded, it is assumed that the user application follow to the [Fail-fast](https://en.wikipedia.org/wiki/Fail-fast_system) approach, since updating the metadata at runtime is not possible — only at startup.
> **NOTE**: SQL script that loads metadata from the database is not included in the delivery, as no DBA would allow executing it from a third-party library due to security concerns.
References: [AllowDBNull](https://learn.microsoft.com/en-us/dotnet/api/system.data.datacolumn.allowdbnull) / [MaxLength](https://learn.microsoft.com/en-us/dotnet/api/system.data.datacolumn.maxlength) / [Ordinal](https://learn.microsoft.com/en-us/dotnet/api/system.data.datacolumn.ordinal) / [Unique](https://learn.microsoft.com/en-us/dotnet/api/system.data.datacolumn.unique) / [ConstraintException](https://learn.microsoft.com/ru-ru/dotnet/api/system.data.constraintexception) / [NoNullAllowedException](https://learn.microsoft.com/ru-ru/dotnet/api/system.data.nonullallowedexception)
# Related projects
- [npgsql.tvp](https://github.com/0UserName/npgsql.tvp)