oracle / dotnet-db-samples

.NET code samples for Oracle database developers #OracleDotNet
http://otn.oracle.com/dotnet
MIT License
413 stars 191 forks source link

Compiling of models: The type mapping used is incompatible with a compiled model #354

Closed chefarbeiter closed 5 months ago

chefarbeiter commented 8 months ago

I use compiled models to improve performance. This still worked with the Oracle Data Provider for EF7, but no longer from EF8 onwards, as the necessary adjustments were not made.

The problem can be reproduced with the following minimal example: Sample.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Oracle.EntityFrameworkCore" Version="8.21.121" />
  </ItemGroup>
</Project>

Program.cs

using Microsoft.EntityFrameworkCore;

namespace Sample;

public class SampleContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseOracle();
    public DbSet<SampleEntity> SampleEntities { get; set; }
}

public class SampleEntity
{
    public int Id { get; set; }
}

public class Program
{
    public static void Main() => Console.WriteLine("Hello");
}

If I now try to compile the model with the dotnet-ef tool (dotnet ef dbcontext optimize), the following exception is thrown:

System.InvalidOperationException: The type mapping used is incompatible with a compiled model. The mapping type must have a 'public static readonly OracleInt32TypeMapping OracleInt32TypeMapping.Default' property.
   at Microsoft.EntityFrameworkCore.Design.Internal.CSharpRuntimeAnnotationCodeGenerator.CreateDefaultTypeMapping(CoreTypeMapping typeMapping, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
   at Microsoft.EntityFrameworkCore.Design.Internal.RelationalCSharpRuntimeAnnotationCodeGenerator.Create(CoreTypeMapping typeMapping, CSharpRuntimeAnnotationCodeGeneratorParameters parameters, ValueComparer valueComparer, ValueComparer keyValueComparer, ValueComparer providerValueComparer)
   at Microsoft.EntityFrameworkCore.Design.Internal.ICSharpRuntimeAnnotationCodeGenerator.Create(CoreTypeMapping typeMapping, IProperty property, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
   at Microsoft.EntityFrameworkCore.Scaffolding.Internal.CSharpRuntimeModelCodeGenerator.Create(IProperty property, String variableName, Dictionary`2 propertyVariables, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
   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 contextTypeName)
   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 type mapping used is incompatible with a compiled model. The mapping type must have a 'public static readonly OracleInt32TypeMapping OracleInt32TypeMapping.Default' property.

If the EF7 versions Oracle.EntityFrameworkCore 7.21.13 and Microsoft.EntityFrameworkCore.Design 7.0.15 are used, the model can be compiled without any problems.

alexkeh commented 8 months ago

@chefarbeiter Thanks for reporting this bug! I've been able to reproduce the problem in Oracle EF Core 8 and the optimize option is working with EF Core 7. I opened bug 36179457. We'll have an Oracle dev team member review the problem.

ChristopheLav commented 5 months ago

Hello @alexkeh,

I see a new package release today but I continue to encounter this issue related to compiled model:

System.InvalidOperationException: The type mapping used is incompatible with a compiled model. The mapping type must have a 'public static readonly MySQLStringTypeMapping MySQLStringTypeMapping.Default' property.

Is the new release contains the fixes related to compiled models since .NET 8 ?

alexkeh commented 5 months ago

@ChristopheLav Yes. The 21.14 release contains the Oracle EF Core compiled models fix.

Your specific error occurs with MySQLStringTypeMapping. This appears to be a MySQL provider property, not an ODP.NET one.

ChristopheLav commented 5 months ago

@alexkeh Ok - where is the right place to report this error ? The compiled models continue to not working correctly due to the lack of full .NET 8 changes implementation. I hope the next servicing release definitively fix the issue(s).

Thank you for your help.

alexkeh commented 5 months ago

@ChristopheLav If you are using the Pomelo MySQL EF Core provider, you can start try their GitHub page.

ChristopheLav commented 5 months ago

@alexkeh I'm not using Pomelo but the MySQL one 😉

If I do one research on the MySQL provider code I see the missing part: https://github.com/mysql/mysql-connector-net/blob/8.x/EFCore/src/Storage/Internal/MySQLStringTypeMapping.cs

System.InvalidOperationException: The type mapping used is incompatible with a compiled model. The mapping type must have a 'public static readonly MySQLStringTypeMapping MySQLStringTypeMapping.Default' property.

I think some changes like that is required to support correctly the Compiled Models with .NET 8 : https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/pull/1839/files

Since the mysql/mysql-connector-net repo has the issues disabled, I can't post here. Can you help with that please ?

alexkeh commented 5 months ago

@ChristopheLav I forwarded your issue to a MySQL dev manager and product manager for .NET to advise on how to move forward with resolving this error.

ChristopheLav commented 5 months ago

@alexkeh thank you so much 👍