MoonStorm / FastCrud

fast .NET ORM for strongly typed people
MIT License
506 stars 128 forks source link

2.6.7 -> 3.0.43 Breaks JOIN statements #154

Closed aizuon closed 2 years ago

aizuon commented 2 years ago

The following statement does not work in latest update:

var plrDto = (await db.FindAsync<PlayerDto>(statement => statement
                    .Where($"{nameof(PlayerDto.id):C} = {nameof(message.AccountId):P}")
                    .Include<CharacterDto>(join => join.LeftOuterJoin())
                    .WithParameters(new {message.AccountId}))).FirstOrDefault();

Simplified DTOs:

[Table("players")]
public class PlayerDto
{
    [Key]
    public uint id { get; set; }

    public IEnumerable<CharacterDto> Characters { get; set; }
}

[Table("characters")]
public class CharacterDto
{
    [Key]
    public ulong id { get; set; }

    [ForeignKey(nameof(player))]
    public uint player_id { get; set; }
    public PlayerDto player { get; set; }
}

I feel like because both PlayerDto and CharacterDto contain id columns, it throws this error. Because when the Include call is deleted, the call does not throw any exceptions. Also, when id column in CharacterDto is named to something like id2, the call also does not throw the exception.

Stack trace:

MySqlConnector.MySqlException (0x80004005): Column 'id' in where clause is ambiguous
   at MySqlConnector.Core.ServerSession.ReceiveReplyAsyncAwaited(ValueTask`1 task) in /_/src/MySqlConnector/Core/ServerSession.cs:line 958
   at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 43
   at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 129
   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 458
   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.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 323
   at Dapper.SqlMapper.MultiMapAsync[TReturn](IDbConnection cnn, CommandDefinition command, Type[] types, Func`2 map, String splitOn) in /_/Dapper/SqlMapper.Async.cs:line 960
   at Dapper.FastCrud.SqlStatements.GenericSqlStatements`1.BatchSelectAsync(IDbConnection connection, AggregatedSqlStatementOptions statementOptions)

MySql connector: https://github.com/mysql-net/MySqlConnector/

aizuon commented 2 years ago

Checking through release notes and wiki, found out that when working with multiple entities, they should be aliased. Issue is resolved.

MoonStorm commented 2 years ago

Yup, that's the best way to target a specific entity in the WHERE clause. Otherwise you have to fully qualify the columns with :TC.