Class ValueObjectDbContextOptionsBuilderExtensions
Namespace: AdCodicem.ValueObjects.EntityFrameworkCore
Assembly: AdCodicem.ValueObjects.EntityFrameworkCore.dll
Adds to the options of a context what the model cannot hold: the translation of what a LINQ query reads of a value object, and the code of the rule a CHECK constraint refused a row under.
public static class ValueObjectDbContextOptionsBuilderExtensions
Inheritance
object ← ValueObjectDbContextOptionsBuilderExtensions
Inherited Members
object.Equals(object?), object.Equals(object?, object?), object.GetHashCode(), object.GetType(), object.MemberwiseClone(), object.ReferenceEquals(object?, object?), object.ToString()
Methods
UseValueObjectCheckErrors(DbContextOptionsBuilder)
Adds the code of the rule a CHECK constraint of AddValueObjectCheckConstraints refused to the error the
database provider throws, under
public static DbContextOptionsBuilder UseValueObjectCheckErrors(this DbContextOptionsBuilder optionsBuilder)
Parameters
optionsBuilder DbContextOptionsBuilder
Options builder of the context.
Returns
The same builder, so calls can be chained.
Remarks
The application's own writes pass the constraints, since the value objects it writes went through their rules. A
constraint fires for an invalid instance a lax read let in and the application writes back, and for a statement
that skips the converter, an ExecuteUpdate setting a column from SQL or raw SQL. Once this is called, the
provider's error carries the code of the rule, which DbUpdateException SaveChanges wraps it in, and from the error ExecuteUpdate, raw SQL or a
migration throws as it is: value_object.out_of_range for CK_Orders_Quantity_Minimum. The error is
neither replaced nor wrapped, so the catch blocks that handle it keep working.
Entity Framework Core hands no interceptor an error a provider reports while the rows of a query are read. On SQL
Server, a raw SQL query that writes rows and reads them back, SqlQuery or FromSql over an
INSERT or an UPDATE with OUTPUT, reports a refusal there, so its error carries no code:
catch. PostgreSQL and SQLite report the
refusal of such a query, over RETURNING, as the command runs, and their error carries the code.
The code is read off the name of the constraint, which ends with its rule, as
It runs when a command or SaveChanges fails, never when one succeeds; once a command interceptor is
registered, though, Entity Framework Core builds the event data of each command it sends, as for any interceptor.
It is an interceptor of the options, so it also runs on a service provider of the application's own, named by
UseInternalServiceProvider. An interceptor of the application's own registered before it sees the error
before the code is added, and Entity Framework Core may log the failure before then too. A second call adds
nothing. Without it, catch, from an
error whoever sent the command.
Exceptions
optionsBuilder is null.
UseValueObjectCheckErrors<TContext>(DbContextOptionsBuilder<TContext>)
Adds the code of the rule a CHECK constraint of AddValueObjectCheckConstraints refused to the error the
database provider throws, under
public static DbContextOptionsBuilder<TContext> UseValueObjectCheckErrors<TContext>(this DbContextOptionsBuilder<TContext> optionsBuilder) where TContext : DbContext
Parameters
optionsBuilder DbContextOptionsBuilder<TContext>
Options builder of the context.
Returns
DbContextOptionsBuilder<TContext>
The same builder, so calls can be chained and its options keep the type of the context.
Type Parameters
TContext
Type of the context.
Remarks
The same as
Exceptions
optionsBuilder is null.
UseValueObjectQueries(DbContextOptionsBuilder)
Translates .Value of a value object, in a LINQ query, to its column, typed as the underlying value.
public static DbContextOptionsBuilder UseValueObjectQueries(this DbContextOptionsBuilder optionsBuilder)
Parameters
optionsBuilder DbContextOptionsBuilder
Options builder of the context.
Returns
The same builder, so calls can be chained.
Remarks
Entity Framework Core translates a comparison between value objects, x.Iban == iban, but nothing a query
reads of the value one holds: x.Iban.Value.StartsWith("FR") or x.Quantity.Value > 2 fail, as
"could not be translated". Once this is called, .Value reads the column itself, under the type mapping of
the underlying type for the column's own store type: WHERE [o].[Iban] LIKE N'FR%', which the index on the
column serves, and a parameter compared with it is declared as the column is, nvarchar(34). An optional
value object, a property inside a JSON column, an element of a primitive collection and a construction of a
generic value object are translated too.
Only a property this package maps is translated: through ConfigureValueObjects,
HasValueObjectConversion, ConfigureEntityIds or HasEntityIdConversion, whose converters
store the bare value, including where Entity Framework Core composes one with its own conversion of the
underlying type, a int column, say. A property mapped through a converter of the
application's own, as a value object over
A column of a table is read as it stands. Anything else, the element of a collection, a column an optional
navigation joins in, a COALESCE, is converted to the underlying type by a CAST to its own store type,
which Entity Framework Core 11 leaves out of the SQL.
.Value reads what the column holds, in a projection too: a strict context,
ConfigureValueObjects(strict: true), validates a value object it materializes, not a .Value a query
projects. Project the value object to have it validated.
Nothing but .Value is translated: ToString(), which follows the formatting hooks, and
EF.Property still fail, and so does .Value of an element of a collection passed as a parameter, which
has no type mapping yet when it is translated; a conversion operator stays the cast Entity Framework Core writes,
to the unbounded type.
The translation runs once per query shape, which Entity Framework Core caches: nothing more runs per execution.
A query precompiled by dotnet ef dbcontext optimize --precompile-queries carries the SQL it wrote, so the
options the design-time context is built with call this too, or the precompilation fails on that query. The
translator works on a relational provider; with any other, this does nothing.
Entity Framework Core adds the translator to the service provider it builds for the context, never to one the
application hands it through UseInternalServiceProvider: a context started on such a provider throws an
IDbContextOptionsExtension.ApplyServices.
Exceptions
optionsBuilder is null.
UseValueObjectQueries<TContext>(DbContextOptionsBuilder<TContext>)
Translates .Value of a value object, in a LINQ query, to its column, typed as the underlying value.
public static DbContextOptionsBuilder<TContext> UseValueObjectQueries<TContext>(this DbContextOptionsBuilder<TContext> optionsBuilder) where TContext : DbContext
Parameters
optionsBuilder DbContextOptionsBuilder<TContext>
Options builder of the context.
Returns
DbContextOptionsBuilder<TContext>
The same builder, so calls can be chained and its options keep the type of the context.
Type Parameters
TContext
Type of the context.
Remarks
The same as
Exceptions
optionsBuilder is null.