Pomelo.EntityFrameworkCore.MySql icon indicating copy to clipboard operation
Pomelo.EntityFrameworkCore.MySql copied to clipboard

InvalidOperationException: The property 'Test.Coord' is of type 'Point' which is not supported by the current database provider.

Open GillesFr06 opened this issue 3 years ago • 8 comments

Steps to reproduce

Entity :

public Point Coord { get; set; }

OnModelCreating :

builder.Entity<IntervenantRayonIntervs>(b =>
{
    ...
    b.Property<Point>(x => x.Coord).ValueGeneratedNever().IsRequired().HasColumnType("point").HasSpatialReferenceSystem(4326).HasColumnName("Coord");
    ...
}

Create DbContext :

.UseMySql(configuration.GetConnectionString("Default"), MySqlServerVersion.LatestSupportedServerVersion, x => x.UseNetTopologySuite());

The issue

If I run

dotnet ef migrations add MigrationName
dotnet ef database update

The table is created.

If I launch my project, I have an exception.

2022-02-19 16:31:20.234 +01:00 [ERR] An unhandled exception has occurred while executing the request.
System.InvalidOperationException: The property 'Test.Coord' is of type 'Point' which is not supported by the current database provider. Either change the property CLR type, or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidatePropertyMapping(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Pomelo.EntityFrameworkCore.MySql.Internal.MySqlModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__8_4(IServiceProvider p)
   at ResolveService(ILEmitResolverBuilderRuntimeContext , ServiceProviderEngineScope )
   at ResolveService(ILEmitResolverBuilderRuntimeContext , ServiceProviderEngineScope )
   at ResolveService(ILEmitResolverBuilderRuntimeContext , ServiceProviderEngineScope )
   at ResolveService(ILEmitResolverBuilderRuntimeContext , ServiceProviderEngineScope )
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker()
   at Volo.Abp.EntityFrameworkCore.AbpDbContext`1.Initialize(AbpEfCoreDbContextInitializationContext initializationContext)
   at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider`1.CreateDbContextAsync(IUnitOfWork unitOfWork, String connectionStringName, String connectionString)
   at Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider`1.GetDbContextAsync()
   at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository`2.GetDbSetAsync()
   at Volo.Abp.Identity.EntityFrameworkCore.EfCoreIdentityUserRepository.FindByNormalizedUserNameAsync(String normalizedUserName, Boolean includeDetails, CancellationToken cancellationToken)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Microsoft.AspNetCore.Identity.UserManager`1.FindByNameAsync(String userName)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(String userName, String password, Boolean isPersistent, Boolean lockoutOnFailure)
   at Volo.Abp.Identity.AspNetCore.AbpSignInManager.PasswordSignInAsync(String userName, String password, Boolean isPersistent, Boolean lockoutOnFailure)
   at Volo.Abp.Account.Web.Pages.Account.IdentityServerSupportedLoginModel.OnPostAsync(String action)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.GenericTaskHandlerMethod.Convert[T](Object taskAsObject)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.GenericTaskHandlerMethod.Execute(Object receiver, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResourceFilter()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at IdentityServer4.Hosting.IdentityServerMiddleware.Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events, IBackChannelLogoutService backChannelLogoutService)
   at IdentityServer4.Hosting.MutualTlsEndpointMiddleware.Invoke(HttpContext context, IAuthenticationSchemeProvider schemes)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at IdentityServer4.Hosting.BaseUrlMiddleware.Invoke(HttpContext context)
   at Volo.Abp.AspNetCore.Uow.AbpUnitOfWorkMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Volo.Abp.AspNetCore.MultiTenancy.MultiTenancyMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Builder.ApplicationBuilderAbpJwtTokenMiddlewareExtension.<>c__DisplayClass0_0.<<UseJwtTokenMiddleware>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Volo.Abp.AspNetCore.Tracing.AbpCorrelationIdMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
2022-02-19 16:31:20.259 +01:00 [INF] Request finished HTTP/2 POST https://localhost:44313/Account/Login application/x-www-form-urlencoded 294 - 500 - text/html;+charset=utf-8 427.8807ms

Further technical details

MySQL version: 8.0.27 Operating system: windows server 2022 Pomelo.EntityFrameworkCore.MySql version: 6.0.1 .NET6 C# Blazor abp.io project

GillesFr06 avatar Feb 19 '22 15:02 GillesFr06

@GillesFr06 I am unable to reproduce this isssue with the following code:

Program.cs
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NetTopologySuite;
using NetTopologySuite.Geometries;

namespace IssueConsoleTemplate
{
    public class IceCreamShop
    {
        public int IceCreamShopId { get; set; }
        public string Name { get; set; }
        public Point Location { get; set; }
    }
    
    public class Context : DbContext
    {
        public DbSet<IceCreamShop> IceCreamShops { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            var connectionString = "server=127.0.0.1;port=3306;user=root;password=;database=Issue1619";
            var serverVersion = ServerVersion.AutoDetect(connectionString);

            optionsBuilder
                .UseMySql(
                    connectionString,
                    serverVersion,
                    options => options.UseNetTopologySuite())
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<IceCreamShop>(
                entity =>
                {
                    entity.Property/*<Point>*/(x => x.Location)
                        .ValueGeneratedNever()
                        .IsRequired()
                        //.HasColumnType("point")
                        .HasSpatialReferenceSystem(4326)
                        .HasColumnName("Coord");
                    
                    var factory = NtsGeometryServices.Instance.CreateGeometryFactory(4326);

                    entity.HasData(
                        new IceCreamShop
                        {
                            IceCreamShopId = 1,
                            Name = "Cold & Sweet",
                        
                            // Brandenburg Gate, Berlin, Germany (lat=52.5162746, lon=13.3777041)
                            Location = factory.CreatePoint(new Coordinate(/* lon */ x: 13.3777041, /* lat */ y: 52.5162746))
                        });
                });
        }
    }

    internal static class Program
    {
        private static void Main()
        {
            using var context = new Context();

            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var iceCreamShop = context.IceCreamShops
                .ToList();
            
            Trace.Assert(iceCreamShop.Count == 1);
        }
    }
}
Output (SQL)
warn: Microsoft.EntityFrameworkCore.Model.Validation[10400]
      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 6.0.2 initialized 'Context' using provider 'Pomelo.EntityFrameworkCore.MySql:6.0.2-servicing.1' with options: ServerVersion 8.0.25-mysql SensitiveDataLoggingEnabled DetailedErrorsEnabled using NetTopologySuite

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (9ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE DATABASE `Issue1619`;

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (9ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      ALTER DATABASE CHARACTER SET utf8mb4;

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (37ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE `IceCreamShops` (
          `IceCreamShopId` int NOT NULL AUTO_INCREMENT,
          `Name` longtext CHARACTER SET utf8mb4 NULL,
          `Coord` point NOT NULL /*!80003 SRID 4326 */,
          CONSTRAINT `PK_IceCreamShops` PRIMARY KEY (`IceCreamShopId`)
      ) CHARACTER SET=utf8mb4;

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      INSERT INTO `IceCreamShops` (`IceCreamShopId`, `Coord`, `Name`)
      VALUES (1, X'E6100000010100000057218A6E62C12A40B4603D4915424A40', 'Cold & Sweet');

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT `i`.`IceCreamShopId`, `i`.`Coord`, `i`.`Name`
      FROM `IceCreamShops` AS `i`

The exception you get would be thrown, if the MySqlNetTopologySuiteTypeMappingSourcePlugin is not being used. By default, calling UseNetTopologySuite() as you do should ensure that the plugin is being used. However, depending on your code, this might not be the case (you could verify this in the log output by checking for using NetTopologySuite; see my log output above).

Therefore, please post your full ASP.NET Core Startup.cs dependency injection code in regards to anything Pomelo or EF Core related, so we can take a look at it.

lauxjpn avatar Feb 20 '22 02:02 lauxjpn

Hi Laurents,

Thanks for your time and your answer.

Following your examples, I looked again (already done for 3 days...) everywhere in the projects that compose the abp.io solution.

And finally I found 2 UseMySQL methods.

One in MyProjectDbContextFactory.cs (that one I've already modified) .UseMySql(configuration.GetConnectionString("Default"), MySqlServerVersion.LatestSupportedServerVersion, x => x.UseNetTopologySuite());

and another one in MyProjectEntityFrameworkCoreModule.cs options.UseMySQL();

Then I also modified this second one with options.UseMySQL(x => x.UseNetTopologySuite());

And no more error.

I hope this answer could help other users of abp.io framework.

BUT (yes, there is a "but"), the log file I see (which is "Logs.txt" file in "Logs" directory) doesn't look like yours (even with DBG level activated).

Sample :

2022-02-20 13:39:46.096 +01:00 [INF] Executing ContentResult with HTTP Response ContentType of application/javascript
2022-02-20 13:39:46.097 +01:00 [INF] Executed action Volo.Abp.AspNetCore.Mvc.ProxyScripting.AbpServiceProxyScriptController.GetAll (Volo.Abp.AspNetCore.Mvc) in 168.8224ms
2022-02-20 13:39:46.097 +01:00 [INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ProxyScripting.AbpServiceProxyScriptController.GetAll (Volo.Abp.AspNetCore.Mvc)'
2022-02-20 13:39:46.098 +01:00 [INF] Request finished HTTP/2 GET https://localhost:44313/Abp/ServiceProxyScript - - - 200 17022 application/javascript 175.9761ms
2022-02-20 13:39:46.181 +01:00 [DBG] Executed AbpApplicationConfigurationAppService.GetAsync().
2022-02-20 13:39:46.202 +01:00 [INF] Executing ContentResult with HTTP Response ContentType of application/javascript
2022-02-20 13:39:46.203 +01:00 [INF] Executed action Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationScriptController.Get (Volo.Abp.AspNetCore.Mvc) in 324.6734ms
2022-02-20 13:39:46.203 +01:00 [INF] Executed endpoint 'Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.AbpApplicationConfigurationScriptController.Get (Volo.Abp.AspNetCore.Mvc)'
2022-02-20 13:39:46.205 +01:00 [INF] Request finished HTTP/2 GET https://localhost:44313/Abp/ApplicationConfigurationScript - - - 200 89345 application/javascript 340.7696ms
2022-02-20 13:39:47.809 +01:00 [INF] Request starting HTTP/2 POST https://localhost:44313/Account/Login application/x-www-form-urlencoded 294
2022-02-20 13:39:47.814 +01:00 [INF] No CORS policy found for the specified request.
2022-02-20 13:39:47.814 +01:00 [INF] Executing endpoint '/Account/Login'
2022-02-20 13:39:47.815 +01:00 [INF] Route matched with {page = "/Account/Login", area = "", action = "", controller = ""}. Executing page /Account/Login
2022-02-20 13:39:47.815 +01:00 [INF] Skipping the execution of current filter as its not the most effective filter implementing the policy Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy
2022-02-20 13:39:47.846 +01:00 [INF] Executing handler method Volo.Abp.Account.Web.Pages.Account.LoginModel.OnPostAsync - ModelState is "Valid"
2022-02-20 13:39:48.075 +01:00 [ERR] Current database does not support transactions. Your database may remain in an inconsistent state in an error case.

No mention of any Pomelo information. Maybe you (or someone else) could have an idea why, and what do I have to modify ?

For the main point I reported as a bug, it's finally not a bug, only a configuration pb on my side.

Hope the time you took could help also others.

Again, thanks for everything. Gilles

GillesFr06 avatar Feb 20 '22 13:02 GillesFr06

@GillesFr06 What is the exact (case-sensitive) spelling of the usemysql() methods you are calling?

lauxjpn avatar Feb 20 '22 23:02 lauxjpn

You're right. I didn't noticed the 2 were different.

I confirm :

in MyProjectDbContextFactory.cs .UseMySql

in MyProjectEntityFrameworkCoreModule.cs .UseMySQL

It seems the first one is for EF Core console commands. So I imagine the second is the "real one" for my Blazor project (adding UseNetTopologySuite here makes the project working).

Gilles

GillesFr06 avatar Feb 20 '22 23:02 GillesFr06

.UseMySql() initializes the Pomelo provider. .UseMySQL() initializes Oracle's provider.

Unless there is a good reason not to, you want to use only one or the other. For Pomelo, only call .UseMySql() consistently.

lauxjpn avatar Feb 21 '22 00:02 lauxjpn

In my case. The first one .UseMySql allowed me to use EF Core console commands like Add-Migration and Update-Database. The second one .UseMySQL allowed me to execute my Blazor Web project (MySQL database), without the error I previously posted.

GillesFr06 avatar Feb 22 '22 00:02 GillesFr06

Weird, I didn't know that MySql.EntityFrameworkCore from Oracle had support for NTS.

Out of interest, what is the namespace of the Point type in your IntervenantRayonIntervs class?

mguinness avatar Feb 22 '22 01:02 mguinness

@GillesFr06 No, what I mean is: Use only a single MySQL provider in the entire project/solution.

If you want to use Pomelo, only call UseMySql() everywhere (for console commands and for your Blazor Web project).

Do not mix the Pomelo provider with Oracle's provider in the same project/solution. You will run into issues.

lauxjpn avatar Feb 22 '22 01:02 lauxjpn