Ef Core 2.1 Hasconversion on All Properties of Type Datetime

EF CORE 2.1 HasConversion on all properties of type datetime

Excerpt from EF Core 2.1 Value Conversions documentation topic:

There is currently no way to specify in one place that every property of a given type must use the same value converter. This feature will be considered for a future release.

Until then, you can use the typical loop at the end of the OnModelCreating override where all entity types and properties are discovered:

var dateTimeConverter = new ValueConverter<DateTime, DateTime>(
v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc));

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entityType.GetProperties())
{
if (property.ClrType == typeof(DateTime) || property.ClrType == typeof(DateTime?))
property.SetValueConverter(dateTimeConverter);
}
}

Entity Framework Core : Apply Conversion to all properties of type OptionT in F#

so going off your initial question "I want to setup a generic type conversion for Option types so that EF knows how to handle them." I am assuming you mean you want EF to properly map an option to a "NULL" column of the corresponding base type, and that you are having problems because EF doesn't know how to handle FSharp.Option?

You could instead just use Nullable in place of Option for your EF types, and it will resolve as it does in C#.

So for instance, your example type becomes:

type [<CLIMutable>] User = {
[<DatabaseGenerated(DatabaseGeneratedOption.Identity)>]
UserID : int64
FirstName : string
LastName : string
LastLoggedInTime : Nullable<DateTimeOffset>
}

For types that can not be Nullable but are Options in your domain (strings for example), you just set them as their base type and it will work just fine.

If you are mapping to F# domain types somewhere else, you can just use Option.ToNullable and Option.OfNullable there, or map None to null if the type cannot be nullable as stated above.

Hope this helps!

Storing custom class property like String via OnModelCreating of DBContext .Net Core

I think that you can use this

        protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Owner>()
.Property(o => o.Ownership)
.HasConversion<string>(o => JsonConvert.SerializeObject(o),
db => JsonConvert.DeserializeObject<Ownership>(db));
}

in this case you must use Newtonsoft.Json Nuget package to serialize the object as a json string of Ownership class, the HasConversion() method has an overload that allows to put the ToFormatter and FromFormatter to avoid creating a ValueConverter object, check this https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions if you want to know more about this conversions.

Loop/reflect through all properties in all EF Models to set Column Type

In EF Core v1.1.0 you can use something like this:

foreach (var pb in modelBuilder.Model
.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?))
.Select(p => modelBuilder.Entity(p.DeclaringEntityType.ClrType).Property(p.Name)))
{
pb.ForSqlServerHasColumnType("decimal(13,4)");
}

Update (EF Core 2.x): Starting from EF Core 2.0, the model is built separately for each database provider, so HasAbcXyz methods are replaced with common HasXyz. The updated code (which also skips the explicitly configured properties) looks like this:

foreach (var property in modelBuilder.Model.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
{
if (property.Relational().ColumnType == null)
property.Relational().ColumnType = "decimal(13,4)";
}

Update (EF Core 3.x): With EF Core 3.0 metadata API changes (Relational() extensions removed, properties replaced with Get / Set method pair), the code is as follows:

foreach (var property in modelBuilder.Model.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?)))
{
if (property.GetColumnType() == null)
property.SetColumnType("decimal(13,4)");
}

Update (Entity Framework Core 6): EF Core 6 includes convention model configuration that can be used to achieve this to all types.
The advantage over looping through entities manually, is that this conventions already ignore certain types (like Ignore(), or properties that have Converters).

public class SomeDbContext : DbContext
{
protected override void ConfigureConventions(
ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder
.Properties<decimal>()
.HavePrecision(19, 4);
}
}

How can I map all instances of a CLR property type to a column type in EF Core?

You can create "Custom Conventions" in EF Core like this:

        protected override void OnModelCreating(ModelBuilder builder)
{
foreach (var entity in builder.Model.GetEntityTypes())
{
foreach (var property in entity.GetProperties())
{
if (property.ClrType == typeof(DateTime))
{
property.Relational().ColumnType = "date";
}
}
}
}


Related Topics



Leave a reply



Submit