Npgsql EF Provider 动态脚手架中未定义 NpgsqlValueGenerationStrategy

问题描述

Postgres 13 数据库包含带有串行列的表:

CREATE TABLE algsa
(
    id serial primary key;
   )

使用 Npgsql 数据提供程序在 ASP.NET MVC Core 应用程序中使用下面的代码在运行时搭建脚手架导致异常

Message = CS0103:当前上下文中不存在名称“NpgsqlValueGenerationStrategy”

生成代码包含

                entity.Property(e => e.Id)
                    .HasColumnName("id")
                    .HasAnnotation("Npgsql:ValueGenerationStrategy",NpgsqlValueGenerationStrategy.SerialColumn);

如何修复 Npgsql 核心提供程序以支持它?添加 using 到生成代码,如注释求解器问题所示,但应生成当前代码。 如果脚手架形式命令提示符,则此注解未创建且代码正确。

重现代码

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Npgsql.EntityFrameworkCore.Postgresql.Diagnostics.Internal;
using Npgsql.EntityFrameworkCore.Postgresql.Scaffolding.Internal;
using Npgsql.EntityFrameworkCore.Postgresql.Storage.Internal;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;

        //https://github.com/jdtcn/RuntimeEfCore
            string connectionString = "Host=localhost;Database=dbwithserial";
            var scaffolder = CreatePostgreScaffolder();
            var dbOpts = new DatabaseModelFactoryOptions(schemas: new string[] { "public","firma1" });
            var modelOpts = new ModelReverseEngineerOptions();
            var codeGenopts = new ModelCodeGenerationoptions()
            {
                RootNamespace = "Eeva.Data",ContextName = "EevaContext",ContextNamespace = "Eeva.Data",ModelNamespace = "Eeva.Data",SuppressConnectionStringWarning = true,SuppressOnConfiguring = true
            };

            var scaffoldedModelSources = scaffolder.ScaffoldModel(connectionString,dbOpts,modelOpts,codeGenopts);
            var sourceFiles = new List<string> {
                // "using Npgsql.EntityFrameworkCore.Postgresql.Metadata;" + Environment.NewLine +
                    scaffoldedModelSources.ContextFile.Code
            };

            sourceFiles.AddRange(scaffoldedModelSources.AdditionalFiles.Select(f =>
            f.Code)); ;
            using var pestream = new MemoryStream();
            bool enableLazyLoading = false;
            var result = GenerateCode(sourceFiles,enableLazyLoading).Emit(pestream);
            if (!result.Success)
            {
                var failures = result.Diagnostics
                    .Where(diagnostic => diagnostic.IsWarningAsError ||
                                         diagnostic.Severity == DiagnosticSeverity.Error);

                var error = failures.FirstOrDefault();
                //  Message = CS0103: The name 'NpgsqlValueGenerationStrategy' does not exist in the current context
                throw new Exception($"{error?.Id}: {error?.GetMessage()}");
            }

            var assemblyLoadContext = new AssemblyLoadContext("DbContext",isCollectible: !enableLazyLoading);
            pestream.Seek(0,SeekOrigin.Begin);
            var assembly = assemblyLoadContext.LoadFromStream(pestream);

            var type = assembly.GetType("Eeva.Data.EevaContext"); // "TypedDataContext.Context.DataContext");
            _ = type ?? throw new Exception("DataContext type not found");

            var constr = type.GetConstructor(Type.EmptyTypes);
            _ = constr ?? throw new Exception("DataContext ctor not found");

            DbContext dynamicContext = (DbContext)constr.Invoke(null);

            var entityTypes = dynamicContext.Model.GetEntityTypes();
            Console.WriteLine($"Context contains {entityTypes.Count()} types");
            foreach (var entityType in dynamicContext.Model.GetEntityTypes())
            {
                var items = (IQueryable<object>)dynamicContext.Query(entityType.Name);
                Console.WriteLine($"Entity type: {entityType.ClrType.Name} contains {items.Count()} items");
            }

            static IReverseEngineerScaffolder CreatePostgreScaffolder()
            {
                return new ServiceCollection()
                    .AddEntityFrameworkNpgsql()
                    .AddLogging()
                    .AddEntityFrameworkDesignTimeServices()
                    .AddSingleton<LoggingDeFinitions,NpgsqlLoggingDeFinitions>()
                    .AddSingleton<IRelationalTypeMappingSource,NpgsqlTypeMappingSource>()
                    .AddSingleton<IAnnotationCodeGenerator,AnnotationCodeGenerator>()
                    .AddSingleton<IDatabaseModelFactory,NpgsqlDatabaseModelFactory>()
                    .AddSingleton<IProviderConfigurationCodeGenerator,NpgsqlCodeGenerator>()
                    .AddSingleton<IScaffoldingModelFactory,RelationalScaffoldingModelFactory>()
                    .BuildServiceProvider()
                    .GetrequiredService<IReverseEngineerScaffolder>();
            }


            static List<MetadataReference> CompilationReferences(bool enableLazyLoading)
            {
                var refs = new List<MetadataReference>();
                var referencedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
                refs.AddRange(referencedAssemblies.Select(a => MetadataReference.CreateFromFile(Assembly.Load(a).Location)));

                refs.Add(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));
                refs.Add(MetadataReference.CreateFromFile(Assembly.Load("netstandard,Version=2.0.0.0").Location));
                refs.Add(MetadataReference.CreateFromFile(typeof(System.Data.Common.DbConnection).Assembly.Location));
                refs.Add(MetadataReference.CreateFromFile(typeof(System.Linq.Expressions.Expression).Assembly.Location));

                if (enableLazyLoading)
                {
                    refs.Add(MetadataReference.CreateFromFile(typeof(ProxiesExtensions).Assembly.Location));
                }

                return refs;
            }

            static CSharpCompilation GenerateCode(List<string> sourceFiles,bool enableLazyLoading)
            {
                var options = CSharpParSEOptions.Default.WithLanguageVersion(LanguageVersion.CSharp9);                 var parsedSyntaxTrees = sourceFiles.Select(f => SyntaxFactory.ParseSyntaxTree(f,options));
                return CSharpCompilation.Create($"DataContext.dll",parsedSyntaxTrees,references: CompilationReferences(enableLazyLoading),options: new CSharpCompilationoptions(OutputKind.DynamicallyLinkedLibrary,optimizationLevel: OptimizationLevel.Release,assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default));
            }

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...