Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dotnet ef dbcontext optimize generates invalid code when using an inner type converter #33710

Open
TonyValenti opened this issue May 13, 2024 · 0 comments

Comments

@TonyValenti
Copy link

TonyValenti commented May 13, 2024

File a bug

Run dotnet ef dbcontext optimize on this code:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleApp20 {
    internal class Program {
        static void Main(string[] args) {
            Console.WriteLine("Hello, World!");
        }
    }

    public class MyContextFactory : IDesignTimeDbContextFactory<MyContext> {
        public MyContext CreateDbContext(string[] args) {
            var Builder = new DbContextOptionsBuilder<MyContext>()
                .UseSqlServer()
                ;

            var Options = Builder.Options;

            return new MyContext(Options);
        }
    }

    public class MyContext : DbContext {
        public MyContext(DbContextOptions options) : base(options) {
        }

        public DbSet<Class1> MyClasses => this.Set<Class1>();


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

            modelBuilder.Entity<Class1>()
                .Property(x => x.Enum)
                //.HasConversion<string>()
                .HasConversion(Test.SafeStringToEnumConverter<MidpointRounding>.Default)
                ;


        }

    }

    public class Class1 {
        public long Id { get; set; }
        public string Name { get; set; }
        public MidpointRounding Enum { get; set; }

    }


    internal static class Test {

        internal class SafeStringToEnumConverter<TEnum> : ValueConverter<TEnum, string> where TEnum : struct {

            public static SafeStringToEnumConverter<TEnum> Default { get; } = new();

            public SafeStringToEnumConverter(TEnum UnknownValue = default, ConverterMappingHints? mappingHints = default) : base(ConvertToString(), ConvertToEnum(UnknownValue), mappingHints) {

            }


            protected static Expression<Func<TEnum, string>> ConvertToString() {
                return v => v.ToString()!;
            }

            protected static Expression<Func<string, TEnum>> ConvertToEnum(TEnum UnknownValue) {
                return v => ConvertToEnum(v, UnknownValue);
            }

            public static TEnum ConvertToEnum(string value, TEnum UnknownValue) {

                if (Enum.TryParse<TEnum>(value, out var result)) {
                    return result;
                } else if (Enum.TryParse(value, true, out result)) {
                    return result;
                } else if (ulong.TryParse(value, out var ulongValue)) {
                    return (TEnum)(object)ulongValue;
                } else if (long.TryParse(value, out var longValue)) {
                    return (TEnum)(object)longValue;
                } else {
                    return UnknownValue;
                }

            }
        }
    }
}

Include verbose output

Errors in the code generated will look like this:
(string v) => Test.SafeStringToEnumConverter`1.ConvertToEnum(v, MidpointRounding.ToEven)),

Specifically, notice that it uses SafeStringToEnumConverter`1 and not the full name of the type.

Include provider and version information

EF Core version: 8.0.4
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: NET 8.0
Operating system: WIN
IDE: 17.9.7

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

No branches or pull requests

3 participants