SQL Dialects
Serenity is database-agnostic. The dialect abstraction
(ISqlDialect)
describes the SQL syntax and behavior of a particular database server type (and
version), so that SqlQuery, the criteria system, and the SQL builders can
generate queries that are correct for the target database.
ISqlDialect
ISqlDialect
is a large interface, but you rarely need to implement it yourself. Each built-in
dialect exposes a shared Instance, which is what you pass around. The members
control how Serenity generates SQL:
| Group | Members |
|---|---|
| Identifier quoting | OpenQuote, CloseQuote, QuoteIdentifier, QuoteColumnAlias, QuoteUnicodeString |
| Paging | CanUseSkipKeyword, CanUseOffsetFetch, CanUseRowNumber, UseRowNum, SkipKeyword, TakeKeyword, UseTakeAtEnd, OffsetFormat, OffsetFetchFormat |
| Identity / insert | UseScopeIdentity, UseReturningIdentity, UseReturningIntoVar, ScopeIdentityExpression |
| String concat | CanUseConcat, ConcatOperator |
| Date / time formats | DateFormat, DateTimeFormat, TimeFormat |
| Other behavior | IsLikeCaseSensitive, NeedsBoolWorkaround, NeedsExecuteBlockStatement, MultipleResultsets, UseDateTime2, UnionKeyword, ServerType, AutoQuotedIdentifiers, IsReservedKeyword |
Several members have sensible default values (via default interface members). For
example CanUseConcat defaults to true and AutoQuotedIdentifiers defaults to
null, which means SqlSettings.AutoQuotedIdentifiers is used.
ServerType
ServerType
is an enum of the server families Serenity knows about:
Firebird, MySql, Oracle, Postgres, Sqlite, SqlServer
Dialects return one of these from their ServerType property.
Built-in Dialects
Serenity ships a dialect for each supported server, exposed as a static
Instance:
| Dialect | Server |
|---|---|
FirebirdDialect |
Firebird |
MySqlDialect |
MySQL |
PostgresDialect |
PostgreSQL |
SqliteDialect |
SQLite |
SqlServer2000Dialect |
SQL Server 2000 |
SqlServer2005Dialect |
SQL Server 2005 |
SqlServer2008Dialect |
SQL Server 2008 |
SqlServer2012Dialect |
SQL Server 2012+ |
OracleDialect |
Oracle |
Oracle12cDialect |
Oracle 12c |
SQL Server dialects inherit from one another, so
SqlServer2012Dialectis aSqlServer2008Dialect, which is aSqlServer2005Dialect, etc.
Resolving a Dialect
ISqlDialectMapper
maps a provider name or a dialect type name to an ISqlDialect instance:
public interface ISqlDialectMapper
{
ISqlDialect TryGet(string dialectOrProviderName);
}
The default implementation,
DefaultSqlDialectMapper,
maps well-known ADO.NET provider names:
| Provider name | Dialect |
|---|---|
System.Data.SqlClient, Microsoft.Data.SqlClient |
SqlServer2012Dialect |
FirebirdSql.Data.FirebirdClient |
FirebirdDialect |
Npgsql |
PostgresDialect |
MySql.Data.MySqlClient, MySqlConnector |
MySqlDialect |
System.Data.SQLite, Microsoft.Data.SQLite |
SqliteDialect |
System.Data.OracleClient, Oracle.ManagedDataAccess.Client |
OracleDialect |
If a provider name isn't found, it also tries to resolve a dialect type by its
name (e.g. SqlServer2005 or a full type name), which is how a connection's
Dialect setting is resolved. See
Connections and Transactions for how a connection picks the
dialect.
SqlSettings
SqlSettings
holds global SQL configuration:
DefaultDialect— the dialect used when one isn't otherwise determined. It defaults toSqlServer2012Dialect. Set it once at application start:SqlSettings.DefaultDialect = SqliteDialect.Instance;Not all queries fall back to this. A connection's dialect is derived from its
providerName(or an explicitDialectsetting inappsettings.json), so a global default only applies where no more specific dialect was resolved.AutoQuotedIdentifiers— whether to automatically quote identifiers. Defaults totrue. Used by the dialect and bySqlSyntaxwhen quoting is needed.DefaultCommandTimeout— an optional default command timeout.SetLocalDialect(dialect)— sets a dialect for the current thread/async context only. This is useful for background tasks and unit tests, where you want to override the dialect locally without affecting the application-wide default:SqlSettings.SetLocalDialect(SqliteDialect.Instance);
Custom Dialects
If you need a server that isn't covered, implement ISqlDialect (or derive from
a built-in dialect and override the members that differ) and register it. A
custom dialect can also implement
ISqlExpressionTranslator
to customize the SQL generated for dynamic expression attributes (such as
ConcatExpressionAttribute):
public interface ISqlExpressionTranslator
{
// Return null if you don't handle the given expression type.
string Translate(object expression);
}
When a dialect implements this interface, Serenity asks it to translate each
expression; returning null means the default behavior is used.
See Also
- Connections and Transactions — how a connection picks its dialect
- Fluent SQL — how dialects affect generated
SELECT/ paging SQL - SQL Data Manipulation — dialect-specific upsert statements
- SQL Query Utilities — translating SQL for a target dialect