代码之家  ›  专栏  ›  技术社区  ›  Natalie Perret

使用Contains?查询时,不调用C#中EntityFramework Core的注册转换?有什么解决办法吗?

  •  0
  • Natalie Perret  · 技术社区  · 6 年前

    我试图弄清楚为什么为我的 SqliteDbContext 当 Contains 在请求中是必要的:

    public static class FSharpOptionExtensions
    {
        public static T DefaultFromOption<T>(this FSharpOption<T> option)
            where T : IEquatable<T> =>
            (FSharpOption<T>.get_IsNone(option)
                ? default
                : option.Value)!;
    
        public static FSharpOption<T> ToOption<T>(this T source)
            where T : IEquatable<T> =>
            source.Equals(default)
                ? FSharpOption<T>.None
                : FSharpOption<T>.Some(source);
    }
    
    public class SqliteDbContext : DbContext
    {
        public DbSet<SqliteRecord>? Records { get; set; }
    
        public SqliteDbContext() // : base()
        {
        }
    
        public SqliteDbContext(DbContextOptions<SqliteDbContext> options) : base(options)
        {
        }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            var faker = new Faker();
            var recordCount = faker.Random.Int(500, 1000);
            var records = Enumerable
                .Range(1, recordCount)
                .Select(index => new SqliteRecord
                {
                    Id = index,
                    Integer = faker.Random.Long(),
                    Real = faker.Random.Double(),
                    NullableText = faker.Name.FullName().OrNull(faker, .2f),
                    NonNullableText = faker.Commerce.Product(),
                    FSharpOptionText = FSharpOption<string>.Some(faker.Vehicle.Manufacturer())
                        .OrDefault(faker, 0.5f, FSharpOption<string>.None)
                });
    
            modelBuilder
                .Entity<SqliteRecord>()
                .Property(x => x.FSharpOptionText)
                .IsRequired(false)
                .HasConversion(new ValueConverter<FSharpOption<string>?, string>(
                    option => option!.DefaultFromOption(),
                    value => value.ToOption()));
    
            modelBuilder
                .Entity<SqliteRecord>()
                .HasKey(x => x.Id);
    
            modelBuilder
                .Entity<SqliteRecord>()
                .ToTable("Records")
                .HasData(records);
        }
    }
    
    var records = await _dbContext.Records.Select(x => new
    {
        Id = x.Id,
        Integer = x.Integer,
        Real = x.Real,
        NullableText = x.NullableText,
        NonNullableText = x.NonNullableText,
        FSharpOptionText = x.FSharpOptionText!.DefaultFromOption()
    }).Where(s =>
        s.NullableText!.ToLower().Contains("d") ||
        s.NonNullableText!.ToLower().Contains("d") ||
        s.FSharpOptionText.ToLower().Contains("d")
    ).ToListAsync();
    

    我得到这个错误:

    系统。InvalidOperationException:LINQ表达式“DbSet()”
    .其中(s=>s.NullableText.ToLower()。包含(“d”)|| s.NonNullableText。ToLo w()。包含(“d”)|| s.FSharpOptionText
    .DefaultFromOption()。ToLow()。无法翻译包含(“d”)的“”。

    要么以可翻译的形式重写查询,要么通过插入对AsEnumerable()、AsAsyncEnumer的调用来显式切换到客户端求值 able()、ToList()或ToListAsync()。请参阅 https://go.microsoft.com/fwlink/?linkid= 2101038了解更多信息。

    在微软。EntityFrameworkCore。查询。可查询方法翻译表达式Vi sitor.g_CheckTranslated|15_0(已翻译的ShapedQueryExpression, <&>c_DisplayClass15_0&)
    在微软。EntityFrameworkCore。查询。可查询方法翻译表达式Vi sitor。VisitMethodCall(方法调用表达式方法调用表达式)
    在系统。林克。表达。方法调用表达式。接受(表达访客来访 tor)
    在系统。林克。表达。表现访客。访问(表达式节点) 在微软。EntityFrameworkCore。查询。可查询方法翻译表达式Vi sitor。VisitMethodCall(方法调用表达式方法调用表达式) 在系统。林克。表达。方法调用表达式。接受(表达访客来访 tor) 在系统。林克。表达。表现访客。访问(表达式节点) 在微软。EntityFrameworkCore。查询。QueryCompilationContext。CreateQueryExe 割接[TResult](表达式查询) 在微软。EntityFrameworkCore。储存。数据库。编译查询[TResult](表达式 会话查询,布尔异步) 在微软。EntityFrameworkCore。查询。内部。查询编译器。编译器QueryCor e[TResult](ViewModel数据库、表达式查询、IModel模型、布尔异步) 在微软。EntityFrameworkCore。查询。内部。查询编译器&<>c_DisplayCla ss12_0 1.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQu eryCore[TFunc](Object cacheKey, Func 1个编译器) 在微软。EntityFrameworkCore。查询。内部。编译的QueryCache。GetOrAddQu ery[TResult](对象cacheKey,函数 1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TR esult](Expression query, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAs ync[TResult](Expression expression, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable 1.GetAsyncEnu merator(取消令牌取消令牌) 在系统。运行时间。编译器服务。已配置取消异步枚举 1.GetA syncEnumerator() at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsy nc[TSource](IQueryable 1来源,取消令牌取消令牌)

    从那以后,这对我来说就没什么意义了 the conversion is supposed to be applied :

    值转换器允许在读取或写入数据库时转换属性值。这种转换可以是从一个值到另一个相同类型的值(例如,加密字符串),或者从一个类型的值转换到另一种类型的值,例如,将枚举值转换为数据库中的字符串

    除非“阅读”在“查询”时不适用,如果真是这样,想知道是否有任何解决方法?是否有任何机制可以扩展表达式的解析方式?


    顺便说一句,下面的查询工作得很好:

    var records = await _dbContext.Records.Select(x => new
    {
        Id = x.Id,
        Integer = x.Integer,
        Real = x.Real,
        NullableText = x.NullableText,
        NonNullableText = x.NonNullableText,
        FSharpOptionText = x.FSharpOptionText!.DefaultFromOption()
    }).Where(x => x.Id == 1).ToListAsync();
    
    info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
          Entity Framework Core 5.0.0-preview.6.20312.4 initialized 'SqliteDbContext
    ' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: None
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeou
    t='30']
          SELECT "r"."Id", "r"."Integer", "r"."Real", "r"."NullableText", "r"."NonNu
    llableText", "r"."FSharpOptionText"
          FROM "Records" AS "r"
          WHERE "r"."Id" = 1
    
    0 回复  |  直到 6 年前