DapperLib / DapperAOT

Build time tools in the flavor of Dapper

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Generated code set invalid `DbParameter.Size` with Oracle database

bsdayo opened this issue · comments

Describe the bug

I am trying to write my code with Dapper.AOT. When a simple query is executed with Oracle provider,

var result = await connection.QueryAsync<string>(
    "SELECT DISTINCT MY_ROW FROM MY_VIEW WHERE XN = :arg AND XQM = :xqm",
    new { xn, xqm });

...the following exception is thrown:

Unhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
   at Oracle.ManagedDataAccess.Client.OracleParameter.set_Size(Int32 value)
   at Dapper.AOT.<dapper_aot_repro_231207_generated>F693EEE48F7739B4ABF5C1A3B26A697291B752118758EC20DF1C53DCA2012F7F5__DapperGeneratedInterceptors.CommandFactory0.AddParameters(UnifiedCommand& cmd, Object args) in C:\Users\bs\Code\Tests\dapper-aot-repro-231207\Dapper.AOT.Analyzers\Dapper.CodeAnalysis.DapperInterceptorGenerator\dapper-aot-repro-231207.generated.cs:line 52
   at Dapper.CommandFactory`1.Initialize(UnifiedCommand& cmd, String sql, CommandType commandType, T args) in /_/src/Dapper.AOT/CommandFactory.cs:line 195
   at Dapper.CommandFactory`1.GetCommand(DbConnection connection, String sql, CommandType commandType, T args) in /_/src/Dapper.AOT/CommandFactory.cs:line 186
   at Dapper.AOT.<dapper_aot_repro_231207_generated>F693EEE48F7739B4ABF5C1A3B26A697291B752118758EC20DF1C53DCA2012F7F5__DapperGeneratedInterceptors.CommonCommandFactory`1.GetCommand(DbConnection connection, String sql, CommandType commandType, T args) in C:\Users\bs\Code\Tests\dapper-aot-repro-231207\Dapper.AOT.Analyzers\Dapper.CodeAnalysis.DapperInterceptorGenerator\dapper-aot-repro-231207.generated.cs:line 26
   at Dapper.Command`1.GetCommand(TArgs args) in /_/src/Dapper.AOT/CommandT.cs:line 79
   at Dapper.Command`1.QueryBufferedAsync[TRow](TArgs args, RowFactory`1 rowFactory, Int32 rowCountHint, CancellationToken cancellationToken) in /_/src/Dapper.AOT/CommandT.Query.cs:line 72
   at Dapper.Command`1.QueryBufferedAsync[TRow](TArgs args, RowFactory`1 rowFactory, Int32 rowCountHint, CancellationToken cancellationToken) in /_/src/Dapper.AOT/CommandT.Query.cs:line 98
   at Dapper.DapperAotExtensions.AsEnumerableAsync[TValue](Task`1 values) in /_/src/Dapper.AOT/DapperAotExtensions.cs:line 23
   at Program.<Main>$(String[] args) in C:\Users\bs\Code\Tests\dapper-aot-repro-231207\Program.cs:line 12
   at Program.<Main>$(String[] args) in C:\Users\bs\Code\Tests\dapper-aot-repro-231207\Program.cs:line 12
   at Program.<Main>(String[] args)

When I look at the generated code, I see that the Size property is set to -1, which caused the exception.

// ...
private sealed class CommandFactory0 : CommonCommandFactory<object?> // <anonymous type: string xn, string xqm>
{
    // ...
    public override void AddParameters(in global::Dapper.UnifiedCommand cmd, object? args)
    {
        var typed = Cast(args, static () => new { xn = default(string), xqm = default(string) }); // expected shape
        var ps = cmd.Parameters;
        global::System.Data.Common.DbParameter p;
        p = cmd.CreateParameter();
        p.ParameterName = "xqm";
        p.DbType = global::System.Data.DbType.String;
        p.Size = -1;   // HERE
        p.Direction = global::System.Data.ParameterDirection.Input;
        p.Value = AsValue(typed.xqm);
        ps.Add(p);
        // ...
    }
    // ...
}
// ...

Everything works fine without using Native AOT.

  • Database backend: Oracle
  • Dapper version: 2.1.24
  • Dapper.AOT version: 1.0.23
  • Oracle.ManagedDataAccess.Core version: 3.21.120

To Reproduce

The reproducible project is located here

Expected behavior

The query works.

Additional context

  • .NET SDK version: 8.0.100

Interesting; this is indeed a minor change from Dapper; in vanilla Dapper, the behavior of string is:

  • if length <= 4000, set 4000 (using fixed value avoids constant recompilation with different inputs)
  • otherwise, use -1 (which on various providers means max)

In AOT, it is:

  • if [DbValue] is specifed with a size, use that
  • otherwise, use -1

This is clearly a change; I'll tweak it to behave identically to Dapper vanilla in the fallback scenario

1.0.26 is now available on myget, https://www.myget.org/F/dapper/api/v3/index.json - are you able to verify fix? (I don't have Oracle)

I apologize for the delay. I've been so busy lately that I forgot about it. I'm so sorry.

After upgrading everything works well. Thank you for the quick fix!