dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.75k stars 3.18k forks source link

Compiled model with value converters #25187

Closed ZvonimirMatic closed 3 years ago

ZvonimirMatic commented 3 years ago

I was unable to create a compiled model (#1906) if there was a custom value converter in the model. The problem is related to EF Core version 6.0 preview 5. EF Core tools (dotnet ef) are also version 6 preview 5. To reproduce the problem you can create an application (dotnet new web --name CompiledModelConverter), install preview 5 versions of Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Design and replace the content of Startup.cs with the following code:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace CompiledModelConverter
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MyDbContext>(options => options.UseSqlServer("dummy-connection-string"));
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }

    public class MyEntity
    {
        public string MyProperty { get; set; }
    }

    public class MyDbContext : DbContext
    {
        public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<MyEntity>()
                .HasNoKey();

             modelBuilder.Entity<MyEntity>()
                 .Property(x => x.MyProperty)
                 .HasConversion(new TrimConverter());
        }
    }

    public class TrimConverter : ValueConverter<string, string>
    {
        public TrimConverter() : base(x => x.Trim(), x => x.Trim()) { }
    }
}

Now running the command dotnet ef dbcontext optimize --verbose produces the following error:

Using project 'C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj'.
Using startup project 'C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj'.
Writing 'C:\projects\testing\CompiledModelConverter\obj\CompiledModelConverter.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\zvoni\AppData\Local\Temp\tmp75C4.tmp /verbosity:quiet /nologo C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj
Writing 'C:\projects\testing\CompiledModelConverter\obj\CompiledModelConverter.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\zvoni\AppData\Local\Temp\tmp7864.tmp /verbosity:quiet /nologo C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj
Build started...
dotnet build C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj /verbosity:quiet /nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.44
Build succeeded.
dotnet exec --depsfile C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.deps.json --additionalprobingpath C:\Users\zvoni\.nuget\packages --additionalprobingpath C:\Microsoft\Xamarin\NuGet --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.runtimeconfig.json C:\Users\zvoni\.dotnet\tools\.store\dotnet-ef\6.0.0-preview.5.21301.9\dotnet-ef\6.0.0-preview.5.21301.9\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll dbcontext optimize --assembly C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.dll --startup-assembly C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.dll --project-dir C:\projects\testing\CompiledModelConverter\ --root-namespace CompiledModelConverter --language C# --working-dir C:\projects\testing\CompiledModelConverter --verbose
Using assembly 'CompiledModelConverter'.
Using startup assembly 'CompiledModelConverter'.
Using application base 'C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0'.
Using working directory 'C:\projects\testing\CompiledModelConverter'.
Using root namespace 'CompiledModelConverter'.
Using project directory 'C:\projects\testing\CompiledModelConverter\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'CompiledModelConverter'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
Found DbContext 'MyDbContext'.
Finding DbContext classes in the project...
Using context 'MyDbContext'.
Finding design-time services referenced by assembly 'CompiledModelConverter'...
Finding design-time services referenced by assembly 'CompiledModelConverter'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding IDesignTimeServices implementations in assembly 'CompiledModelConverter'...
No design-time services were found.
System.InvalidOperationException: The property 'MyEntity.MyProperty' has a value converter configured. Use 'HasConversion' to configure the value converter type.
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.Create(IProperty property, Dictionary`2 propertyVariables, CSharpRuntimeAnnotationCodeGeneratorParameters parameters, String className)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.CreateEntityType(IEntityType entityType, IndentedStringBuilder mainBuilder, IndentedStringBuilder methodBuilder, SortedSet`1 namespaces, String className, Boolean nullable)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.GenerateEntityType(IEntityType entityType, String namespace, String className, Boolean nullable)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.GenerateModel(IModel model, CompiledModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CompiledModelScaffolder.ScaffoldModel(IModel model, String outputDir, CompiledModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.Optimize(String outputDir, String modelNamespace, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeImpl(String outputDir, String modelNamespace, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.Optimize.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The property 'MyEntity.MyProperty' has a value converter configured. Use 'HasConversion' to configure the value converter type.

I tried replacing the converter configuration as suggested in the issue #1906 with the following code:

 modelBuilder.Entity<MyEntity>()
    .Property(x => x.MyProperty)
    .HasConversion(typeof(TrimConverter), default(ValueComparer));

Now running the same command produces the following error:

Using project 'C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj'.
Using startup project 'C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj'.
Writing 'C:\projects\testing\CompiledModelConverter\obj\CompiledModelConverter.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\zvoni\AppData\Local\Temp\tmpA921.tmp /verbosity:quiet /nologo C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj
Writing 'C:\projects\testing\CompiledModelConverter\obj\CompiledModelConverter.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\zvoni\AppData\Local\Temp\tmpABF1.tmp /verbosity:quiet /nologo C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj
Build started...
dotnet build C:\projects\testing\CompiledModelConverter\CompiledModelConverter.csproj /verbosity:quiet /nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.39
Build succeeded.
dotnet exec --depsfile C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.deps.json --additionalprobingpath C:\Users\zvoni\.nuget\packages --additionalprobingpath C:\Microsoft\Xamarin\NuGet --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.runtimeconfig.json C:\Users\zvoni\.dotnet\tools\.store\dotnet-ef\6.0.0-preview.5.21301.9\dotnet-ef\6.0.0-preview.5.21301.9\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll dbcontext optimize --assembly C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.dll --startup-assembly C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0\CompiledModelConverter.dll --project-dir C:\projects\testing\CompiledModelConverter\ --root-namespace CompiledModelConverter --language C# --working-dir C:\projects\testing\CompiledModelConverter --verbose
Using assembly 'CompiledModelConverter'.
Using startup assembly 'CompiledModelConverter'.
Using application base 'C:\projects\testing\CompiledModelConverter\bin\Debug\net6.0'.
Using working directory 'C:\projects\testing\CompiledModelConverter'.
Using root namespace 'CompiledModelConverter'.
Using project directory 'C:\projects\testing\CompiledModelConverter\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'CompiledModelConverter'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
Found DbContext 'MyDbContext'.
Finding DbContext classes in the project...
Using context 'MyDbContext'.
System.InvalidOperationException: The property 'MyEntity.MyProperty' is of type 'string' which is not supported by the current database provider. Either change the property CLR type, or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidatePropertyMapping(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.SqlServer.Infrastructure.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.<>c.<Initialize>b__4_0(ValueTuple`4 args)
   at Microsoft.EntityFrameworkCore.Infrastructure.AnnotatableBase.<>c__30`2.<GetOrAddRuntimeAnnotationValue>b__30_0(String n, ValueTuple`3 t)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd[TArg](TKey key, Func`3 valueFactory, TArg factoryArgument)
   at Microsoft.EntityFrameworkCore.Infrastructure.AnnotatableBase.GetOrAddRuntimeAnnotationValue[TValue,TArg](String name, Func`2 valueFactory, TArg factoryArgument)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.Optimize(String outputDir, String modelNamespace, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeImpl(String outputDir, String modelNamespace, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.Optimize.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The property 'MyEntity.MyProperty' is of type 'string' which is not supported by the current database provider. Either change the property CLR type, or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'. 

Removing the conversion configuration all together results in a successful generation of compiled model. So does using a generic overload of HasConversion method without specifying a converter, for example:

modelBuilder.Entity<MyEntity>()
    .Property(x => x.MyProperty)
    .HasConversion<decimal>();

Using one of the built in converters such as StringToBoolConverter does not work, it produces same error as a custom value converter.

I have tried this with SQL Server and SQLite and behavior is the same.

I have also tried using PostgreSQL but I get the following error whether I have value converters configured or not: Could not load type 'System.DateOnly' from assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. I suppose that PostgreSQL error is related to something else or I might have misconfigured something (I only installed Npgsql.EntityFrameworkCore.PostgreSQL and replaced .UseSqlServer with .UseNpgsql). I decided to metion

EF Core version: 6.0 preview 5 Database provider: Microsoft.EntityFrameworkCore.SqlServer, Microsoft.EntityFrameworkCore.SqlLite Target framework: .NET 6.0 preview 5 Operating system: Windows 10 IDE: VS Code

Spacefish commented 3 years ago

regarding: Could not load type 'System.DateOnly' from assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. with PostgreSQL

I had the same issue on a ubuntu linux server running dotnet 6.0 Preview 2, after updating to Preview 5 the issue was gone. Not sure if the model is pre-compiled on demand or something like that and the issue might happen again, but for me updating to the latest preview fixed it.

roji commented 3 years ago

@Spacefish DateOnly is a new type which was only introduced in .NET 6.0 preview5.

AndriySvyryd commented 3 years ago

Appears to be fixed in 6.0.0-rc1

davidhenley commented 3 years ago

@AndriySvyryd what is the status on DateOnly & TimeOnly conversions in RC1?

Do we still need to write custom converters for SQL Server?

AndriySvyryd commented 3 years ago

Do we still need to write custom converters for SQL Server?

Yes, SQLClient doesn't natively support them yet, see https://github.com/dotnet/SqlClient/issues/1009

aherrick commented 3 years ago

I"m not seeing this fixed in 6 RC1.

                entity.Property(o => o.UsageLogType)
                    .HasMaxLength(10)
                    .HasConversion(new EnumToStringConverter<UsageLogType>());
System.InvalidOperationException: The property 'UsageLog.UsageLogType' has a value converter configured. Use 'HasConversion' to configure the value converter type.
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.Create(IProperty property, Dictionary`2 propertyVariables, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.CreateEntityType(IEntityType entityType, IndentedStringBuilder mainBuilder, IndentedStringBuilder methodBuilder, SortedSet`1 namespaces, String className, Boolean nullable)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.GenerateEntityType(IEntityType entityType, String namespace, String className, Boolean nullable)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.GenerateModel(IModel model, CompiledModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CompiledModelScaffolder.ScaffoldModel(IModel model, String outputDir, CompiledModelCodeGenerationOptions options)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.Optimize(String outputDir, String modelNamespace, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeContextImpl(String outputDir, String modelNamespace, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeContext.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The property 'UsageLog.UsageLogType' has a value converter configured. Use 'HasConversion' to configure the value converter type.
AndriySvyryd commented 3 years ago

@aherrick Use

                entity.Property(o => o.UsageLogType)
                    .HasMaxLength(10)
                    .HasConversion<EnumToStringConverter<UsageLogType>>();