RepoDb.Vertica
A hybrid .NET ORM library for Vertica (using Vertica.Data.VerticaClient).
Install
| Product | Versions |
|---|---|
| .NET | |
| .NET Standard |
README
RepoDb.Vertica β RepoDB for Vertica
The Vertica provider for RepoDB β a fast, lightweight .NET ORM that lets you use raw SQL and fluent operations side by side on the same connection. Built on top of RepoDb and Vertica.Data.VerticaClient.
Important Pages
- GitHub Home β core library and source code.
- Website β full documentation, API reference, and blog.
Community
- GitHub Issues β bug reports and feature requests.
- Microsoft Teams β live Q&A.
- GitHub Discussions β ask questions and share ideas.
- X / Twitter β news and updates.
Dependencies
- Vertica.Data.VerticaClient β the Vertica ADO.NET data provider.
- RepoDb β the RepoDB core library.
Known limitations
- Targets Vertica 3.0 and later. Identity-column detection relies on
RDB$RELATION_FIELDS.RDB$IDENTITY_TYPE, which does not exist on Vertica 2.5 and earlier; tables using the pre-3.0 trigger + generator pattern for auto-increment will not be detected as identity columns. InsertAllbatches real multi-rowINSERT INTO t (...) VALUES (...), (...), ...statements (IDbSetting.IsInsertAllBatchable = true) - a single statement, not multiple;-separated ones, so it doesn't hit Vertica's compound-statement restriction. This matters: Vertica creates a new storage container (ROS) per statement, regardless of whether inserts share a transaction/commit, so one-row-at-a-time inserts exhaust the per-projection ROS container limit ("Too many ROS containers exist") on any sizeableInsertAll. A generated IDENTITY value for a batch is read back with a singleLAST_INSERT_ID()query after the batch, then assigned to each row by computed offset - this assumes Vertica generates IDENTITY values contiguously and in input row order within one multi-row INSERT, which is unverified against a real (especially multi-node) cluster.MergeAllalways executes one statement per row regardless (see below) - Vertica's ADO.NET provider does not support executing multiple separate statements in a single round-trip, unlike SQL Server/MySQL/PostgreSql.- Vertica has neither a native single-statement upsert nor a usable
MERGEfor this purpose: it has noUPDATE OR INSERT ... MATCHINGstatement, and its ANSIMERGEfails outright (error 4711, "Sequence or IDENTITY/AUTO_INCREMENT column in merge query is not supported") against any table carrying an IDENTITY column, whether or not that column is referenced. Nor can a compound (stmt1; stmt2) statement stand in for it:VerticaCommandrefuses to execute one at all once it carries a parameter, on everyExecute*call (it always prepares first internally), not just when.Prepare()is called explicitly.Merge/MergeAlltherefore setIsUseUpsert = true, routing through RepoDb.Core'sExists+Update/Insertfallback - genuinely separate, single-statement round-trips - instead of a single atomic statement. - Vertica has no
RETURNINGclause on any DML. A generated IDENTITY value is instead read back via a separateSELECT LAST_INSERT_ID()query (Vertica's session-scoped equivalent ofSCOPE_IDENTITY(), valid only for IDENTITY columns, not named sequences) - seeVerticaDbHelper.GetScopeIdentity, called automatically by RepoDb.Core'sInsert/InsertAllas a fallback whenever the insert's ownExecuteScalar()doesn't yield a value. - Vertica's driver materializes a
TIMEcolumn's value as a fullDateTimecombined with the current date at the time of the read, not a fixed placeholder date - so a value written and read back would otherwise never compare equal to itself. There is no accessor that returns a bareTimeSpanfor aTIMEcolumn. ApplyVerticaTimeToDateTimePropertyHandlerto anyDateTime-typed property mapped to aTIMEcolumn to re-base it ontoDateTime's default date; it is opt-in (not auto-registered) sincePropertyHandlerMapperregistrations by CLR type are global and would otherwise also affectDATE/TIMESTAMPcolumns.- This only fixes typed-entity queries (
Query<TEntity>,Merge<TEntity>, etc.), sincePropertyHandlerMapperis keyed by(EntityType, PropertyInfo)- an actual CLR property to attach to. Dynamic/ExpandoObjectreads (*ViaTableNameoperations, a dynamicQuery/ExecuteQuery) go through RepoDb.Core's dictionary-binding compiler, which reads the raw driver value directly with no property-handler hook at all. Fixing that path would require wrapping Vertica's (sealed, so un-subclassable)VerticaConnection/VerticaCommand/VerticaDataReaderbehind a from-scratch delegatingDbConnection/DbCommand/DbDataReadertriplet - not implemented. ATIMEcolumn read back through a dynamic path will show today's date instead of a placeholder.
- This only fixes typed-entity queries (
License
Apache-2.0 β Copyright Β© 2020 Michael Camara Pendon
Installation
Install-Package RepoDb.Vertica
Or visit the installation page for more options.
Get Started
Initialize the bootstrapper once at application startup:
GlobalConfiguration
.Setup()
.UseVertica();
Then use any RepoDB operation directly on your VerticaConnection:
Query
using (var connection = new VerticaConnection(ConnectionString))
{
var customer = connection.Query<Customer>(c => c.Id == 10045);
}
Insert
var customer = new Customer
{
FirstName = "John",
LastName = "Doe",
IsActive = true
};
using (var connection = new VerticaConnection(ConnectionString))
{
var id = connection.Insert<Customer>(customer);
}
Update
using (var connection = new VerticaConnection(ConnectionString))
{
var customer = connection.Query<Customer>(10045);
customer.FirstName = "John";
customer.LastUpdatedUtc = DateTime.UtcNow;
var affectedRows = connection.Update<Customer>(customer);
}
Delete
using (var connection = new VerticaConnection(ConnectionString))
{
var customer = connection.Query<Customer>(10045);
var deletedCount = connection.Delete<Customer>(customer);
}
ExecuteQuery
using (var connection = new VerticaConnection(ConnectionString))
{
var customer = connection.ExecuteQuery<Customer>("SELECT * FROM \"Customer\" WHERE (\"Id\" = @Id)", new { Id = 10045 }).FirstOrDefault();
}
ExecuteNonQuery
using (var connection = new VerticaConnection(ConnectionString))
{
var affectedRows = connection.ExecuteNonQuery("UPDATE \"Customer\" SET \"FirstName\" = @FirstName WHERE (\"Id\" = @Id)", new { FirstName = "John", Id = 10045 });
}
ExecuteScalar
using (var connection = new VerticaConnection(ConnectionString))
{
var count = connection.ExecuteScalar<int>("SELECT COUNT(*) FROM \"Customer\"");
}
Visit the get-started page for the full Vertica guide.
License
Apache-2.0 β Copyright Β© 2020 Michael Camara Pendon
Adoption Assessment
A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.