Skip to content

Instantly share code, notes, and snippets.

@roji
Created February 29, 2024 20:45
Show Gist options
  • Save roji/7762062a1726819fb5560d46b3cf66db to your computer and use it in GitHub Desktop.
Save roji/7762062a1726819fb5560d46b3cf66db to your computer and use it in GitHub Desktop.
await using var context = new BlogContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
=> configurationBuilder.Properties<ReadOnlyMemory<byte>>().HaveConversion<ReadOnlyMemoryConverter>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer("Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
private class ReadOnlyMemoryConverter() : ValueConverter<ReadOnlyMemory<byte>, byte[]>(v => v.ToArray(), v => v);
}
public class Blog
{
public int Id { get; set; }
public ReadOnlyMemory<byte> Bytes { get; set; }
}
@paulomorgado
Copy link

Is there something like a IModelCustomizer for configuring conventions?

@roji
Copy link
Author

roji commented Mar 1, 2024

You can take a look at user conventions, but I'm not sure exactly what you're looking for (and specifically what's needed beyond the ConfigureConventions snippet above.

@paulomorgado
Copy link

I'm trying to configure stuff without changing the dbcontext code.

I can customize the model "from the outside":

services
    .AddPooledDbContextFactory<MyDbContext<TData>>(options =>
    {
        options.UseSqlite(connectionString);
        options.ReplaceService<IModelCustomizer, SqliteModelCostumizer<TMessage>>();
    })
    ;

But I haven't found a way to do the same for conventions.

Unless I inject them in the service provider and retrieve them from there.

@roji
Copy link
Author

roji commented Mar 1, 2024

Then you're probably looking for type mapping plugin - that allows you to write a plugin that adds/overrides type mappings in addition to the provider's ones. You can then even publish that plugin as a nuget package, and people can reference it and use it.

For a good example, take a look at the NetTopologySuite plugins in the EF Core repo.

@paulomorgado
Copy link

Looks great.

Now I can write one for DateTimeOffset for Sqlite too. 😄

@roji
Copy link
Author

roji commented Mar 1, 2024

There already is a value converter for DateTimeOffset for Sqlite (converting it to a string) - what exactly are you looking for?

@paulomorgado
Copy link

paulomorgado commented Mar 1, 2024

Is it on by default? Or do I have to do something?
Does it allow queries comparing dates?

    System.InvalidOperationException : The LINQ expression 'DbSet<QueueEntity<TestMessage>>()
    .Where(q => q.DequeueAfter <= __dequeueAfter_0 && q.DequeueAfter < __dequeueAfter_0)' could not be translated.

@roji
Copy link
Author

roji commented Mar 1, 2024

Is it on by default? Or do I have to do something?

It's enabled by default - have you seen some other behavior?

Does it allow queries comparing dates?

No, because comparing the string representations of DateTimeOffset doesn't work - imagine having different time zones there, and then comparing string representations. If you're only storing timestamps in a single timezone (e.g. UTC), you can just use DateTime, which has a default value where comparison is supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment