1

I have the following relation in my MainContext:

modelBuilder.Entity<Project>()
    .HasMany(project => project.Messages)
    .WithMany(message => message.Projects)
    .UsingEntity<ProjectmessageProject>(
        typeBuilder => typeBuilder.HasOne(x => x.Message).WithMany().HasForeignKey(x => x.ProjectmessageId),
        typeBuilder => typeBuilder.HasOne(x => x.Project).WithMany().HasForeignKey(x => x.ProjectIdTest)
    );

I have renamed ProjectId to ProjectIdTest for testing. This is not the cause and I can reverse it. Now, when I try to access ProjectmessageProject, EF Core generates the following SQL query:

SELECT `p0`.`project_id`, `p0`.`projectmessage_id`, `p0`.`folder_id`, `p0`.`ProjectId`, `p0`.`ProjectMessageId`, `p`.`id`
      FROM `projects` AS `p`
      INNER JOIN `projectmessage_project` AS `p0` ON `p`.`id` = `p0`.`ProjectId`
      WHERE `p`.`id` = @__id_0
      ORDER BY `p`.`id`

Now, the problem here is that ProjectId and ProjectMessageId are the property names in the entity. There are no DB columns with these names. They are project_id and projectmessage_id, which are already selected.

Here is the entity:

[Table("projectmessage_project")]
public record ProjectmessageProject : IProjectmessageProject
{
    public Project? Project { get; init; }

    public ProjectMessage? Message { get; init; }

    [NotMapped]
    public UInt64 Id { get; init; }

    [Column("projectmessage_id")]
    public UInt64? ProjectmessageId { get; init; }

    [Column("project_id")]
    public UInt64? ProjectIdTest { get; init; }

    [Column("folder_id")]
    public UInt64? FolderId { get; init; }

}

As you can see as well, Id is marked as NotMapped, but EF Core still tries to access it.

This is the exception I get in the console:

Connection id "0HMMVFK574S69", Request id "0HMMVFK574S69:00000005": An unhandled exception was thrown by the application.

MySqlConnector.MySqlException (0x80004005): Unknown column 'p0.ProjectId' in 'field list'

at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 44
at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 127
at MySqlConnector.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary`2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 456
         at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 56
         at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 330
         at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 272
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
         at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.<PopulateSplitCollection>g__InitializeReader|67_1[TCollection,TElement,TRelatedEntity](RelationalQueryContext queryContext, RelationalCommandCache relationalCommandCache, Boolean detailedErrorsEnabled)
         at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.Execute[TState,TResult](IExecutionStrategy strategy, TState state, Func`2 operation, Func`2 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.PopulateSplitCollection[TCollection,TElement,TRelatedEntity](Int32 collectionId, RelationalQueryContext queryContext, IExecutionStrategy executionStrategy, Boolean detailedErrorsEnabled, SplitQueryResultCoordinator resultCoordinator, RelationalCommandCache relationalCommandCache, Func`3 childIdentifier, IReadOnlyList`1 identifierValueComparers, Func`5 innerShaper, Action`3 relatedDataLoaders)
         at lambda_method138(Closure , QueryContext , IExecutionStrategy , SplitQueryResultCoordinator )
         at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable`1.Enumerator.MoveNext()
         at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteResourceSetAsync(IEnumerable enumerable, IEdmTypeReference resourceSetType, ODataWriter writer, ODataSerializerContext writeContext)
         at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteObjectInlineAsync(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
         at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteObjectAsync(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
         at Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatterHelper.WriteToStreamAsync(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, IODataSerializerProvider serializerProvider)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
         at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
         at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware.InvokeAsync(HttpContext context)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

Thank you for any advice.

I've tried changing around the relation, adding ForeignKeys for the two Properties "Project" and Message, I've added a composite key in the context like this:

modelBuilder.Entity<ProjectmessageProject>().HasKey(x => new
        {
            x.ProjectIdTest,
            x.ProjectmessageId,
            x.FolderId
        });

When I rename "ProjectIdTest" back to "ProjectId", it actually tries to access some "ProjectId1" column in the database.

I've been trying around for like 8 hours. Nothing seems to work.

5
  • 2
    After applying Column properties, have you run new migration? Commented Dec 16, 2022 at 16:12
  • @NikitaChayka you mean these? "[Column("project_id")]" The field project_id exists in the database. It shouldn't create a "ProjectId" or "ProjectmessageId" field in the DB. "project_id" and "projectmessage_id" are already there. I'm not sure why a migration would be nessessary here. I just want EFCore to work with the DB as-is, I have all the data I need there. Commented Dec 16, 2022 at 16:25
  • What's the LINQ query that generates that SQL? I can't repro this issue. Perhaps your entity configuration is not actually running? Commented Dec 16, 2022 at 17:14
  • The query: RequestDb().ProjectmessageProjects.Where(expression). expression in passed as a parameter. How can I check if my entity configuration is running? Commented Dec 19, 2022 at 8:33
  • I've also noticed that when I try to migrate, it actually tries to create those columns and Keys. Commented Dec 19, 2022 at 12:30

1 Answer 1

1

When you add a Navigation Property you need to explicitly configure the foreign keys if your foreign key property names don't comply with the EF Core naming convention (eg : ProjectId). If you don't EF Core will generate those columns, and name them according to the convention. If you want to re-use existing columns for referential integrity you need to configure your entity like the below :


[Table("projectmessage_project")]
public record ProjectmessageProject : IProjectmessageProject
{
    [ForeignKey(nameof(ProjectIdTest))]
    public Project? Project { get; init; }

    [ForeignKey(nameof(ProjectmessageId ))]
    public ProjectMessage? Message { get; init; }

    [NotMapped]
    public UInt64 Id { get; init; }

    [Column("projectmessage_id")]
    public UInt64? ProjectmessageId { get; init; }

    [Column("project_id")]
    public UInt64? ProjectIdTest { get; init; }

    [Column("folder_id")]
    public UInt64? FolderId { get; init; }

}

Mentioned Conventions

Sign up to request clarification or add additional context in comments.

1 Comment

I tried this, it doesn't help. The weird thing is, it's trying to access "'p.ProjectId' in 'field list'", even though I have renamed the Property to "ProjectIdTest" everywhere. Before that, It tried to access ProjectId1. I think it's doing some shadow property fuckery, but I can't figure it out. Also, the Id doesn't have a db-field, and is notmapped, but is still included in the query. very weird.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.