问题描述
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 (将#修改为@)