Skip to content

Commit

Permalink
respect designated DbType when explicitly specified (#100)
Browse files Browse the repository at this point in the history
* respect designated DbType when explicitly specified

* observe additional impacted test
  • Loading branch information
mgravell authored Dec 13, 2023
1 parent a5a7f03 commit 643477a
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/Dapper.AOT.Analyzers/Internal/Inspection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ public readonly struct ElementMember
if (preferredType != dbType)
{ // only preserve the reader method if this matches
readerMethod = null;
dbType = preferredType;
}
}
return dbType;
Expand Down
28 changes: 28 additions & 0 deletions test/Dapper.AOT.Test/Interceptors/DbValueUsage.input.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Dapper;
using System;
using System.Data.Common;
using System.Threading.Tasks;

[DapperAot(enabled: true)]
public static class UsersSqlQueries
{
public sealed class UserIncrementParams
{
[DbValue(Name = "userId")]
public int UserId { get; set; }

[DbValue(Name = "date", DbType = System.Data.DbType.Date)]
public DateTime Date { get; set; }
}

public static async Task IncrementAsync(DbConnection connection, int userId)
{
var date = DateTime.Today;

await connection.ExecuteAsync("""
UPDATE [dbo].[table]
SET [column] = ([column] + 1)
WHERE [Id] = @userId and [Date] = @date
""", new UserIncrementParams() { UserId = userId, Date = date });
}
}
91 changes: 91 additions & 0 deletions test/Dapper.AOT.Test/Interceptors/DbValueUsage.output.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#nullable enable
namespace Dapper.AOT // interceptors must be in a known namespace
{
file static class DapperGeneratedInterceptors
{
[global::System.Runtime.CompilerServices.InterceptsLocationAttribute("Interceptors\\DbValueUsage.input.cs", 22, 26)]
internal static global::System.Threading.Tasks.Task<int> ExecuteAsync0(this global::System.Data.IDbConnection cnn, string sql, object? param, global::System.Data.IDbTransaction? transaction, int? commandTimeout, global::System.Data.CommandType? commandType)
{
// Execute, Async, HasParameters, Text, KnownParameters
// takes parameter: global::UsersSqlQueries.UserIncrementParams
// parameter map: Date UserId
global::System.Diagnostics.Debug.Assert(!string.IsNullOrWhiteSpace(sql));
global::System.Diagnostics.Debug.Assert((commandType ?? global::Dapper.DapperAotExtensions.GetCommandType(sql)) == global::System.Data.CommandType.Text);
global::System.Diagnostics.Debug.Assert(param is not null);

return global::Dapper.DapperAotExtensions.Command(cnn, transaction, sql, global::System.Data.CommandType.Text, commandTimeout.GetValueOrDefault(), CommandFactory0.Instance).ExecuteAsync((global::UsersSqlQueries.UserIncrementParams)param!);

}

private class CommonCommandFactory<T> : global::Dapper.CommandFactory<T>
{
public override global::System.Data.Common.DbCommand GetCommand(global::System.Data.Common.DbConnection connection, string sql, global::System.Data.CommandType commandType, T args)
{
var cmd = base.GetCommand(connection, sql, commandType, args);
// apply special per-provider command initialization logic for OracleCommand
if (cmd is global::Oracle.ManagedDataAccess.Client.OracleCommand cmd0)
{
cmd0.BindByName = true;
cmd0.InitialLONGFetchSize = -1;

}
return cmd;
}

}

private static readonly CommonCommandFactory<object?> DefaultCommandFactory = new();

private sealed class CommandFactory0 : CommonCommandFactory<global::UsersSqlQueries.UserIncrementParams>
{
internal static readonly CommandFactory0 Instance = new();
public override void AddParameters(in global::Dapper.UnifiedCommand cmd, global::UsersSqlQueries.UserIncrementParams args)
{
var ps = cmd.Parameters;
global::System.Data.Common.DbParameter p;
p = cmd.CreateParameter();
p.ParameterName = "userId";
p.DbType = global::System.Data.DbType.Int32;
p.Direction = global::System.Data.ParameterDirection.Input;
p.Value = AsValue(args.UserId);
ps.Add(p);

p = cmd.CreateParameter();
p.ParameterName = "date";
p.DbType = global::System.Data.DbType.Date;
p.Direction = global::System.Data.ParameterDirection.Input;
p.Value = AsValue(args.Date);
ps.Add(p);

}
public override void UpdateParameters(in global::Dapper.UnifiedCommand cmd, global::UsersSqlQueries.UserIncrementParams args)
{
var ps = cmd.Parameters;
ps[0].Value = AsValue(args.UserId);
ps[1].Value = AsValue(args.Date);

}
public override bool CanPrepare => true;

}


}
}
namespace System.Runtime.CompilerServices
{
// this type is needed by the compiler to implement interceptors - it doesn't need to
// come from the runtime itself, though

[global::System.Diagnostics.Conditional("DEBUG")] // not needed post-build, so: evaporate
[global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
sealed file class InterceptsLocationAttribute : global::System.Attribute
{
public InterceptsLocationAttribute(string path, int lineNumber, int columnNumber)
{
_ = path;
_ = lineNumber;
_ = columnNumber;
}
}
}
91 changes: 91 additions & 0 deletions test/Dapper.AOT.Test/Interceptors/DbValueUsage.output.netfx.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#nullable enable
namespace Dapper.AOT // interceptors must be in a known namespace
{
file static class DapperGeneratedInterceptors
{
[global::System.Runtime.CompilerServices.InterceptsLocationAttribute("Interceptors\\DbValueUsage.input.cs", 22, 26)]
internal static global::System.Threading.Tasks.Task<int> ExecuteAsync0(this global::System.Data.IDbConnection cnn, string sql, object? param, global::System.Data.IDbTransaction? transaction, int? commandTimeout, global::System.Data.CommandType? commandType)
{
// Execute, Async, HasParameters, Text, KnownParameters
// takes parameter: global::UsersSqlQueries.UserIncrementParams
// parameter map: Date UserId
global::System.Diagnostics.Debug.Assert(!string.IsNullOrWhiteSpace(sql));
global::System.Diagnostics.Debug.Assert((commandType ?? global::Dapper.DapperAotExtensions.GetCommandType(sql)) == global::System.Data.CommandType.Text);
global::System.Diagnostics.Debug.Assert(param is not null);

return global::Dapper.DapperAotExtensions.Command(cnn, transaction, sql, global::System.Data.CommandType.Text, commandTimeout.GetValueOrDefault(), CommandFactory0.Instance).ExecuteAsync((global::UsersSqlQueries.UserIncrementParams)param!);

}

private class CommonCommandFactory<T> : global::Dapper.CommandFactory<T>
{
public override global::System.Data.Common.DbCommand GetCommand(global::System.Data.Common.DbConnection connection, string sql, global::System.Data.CommandType commandType, T args)
{
var cmd = base.GetCommand(connection, sql, commandType, args);
// apply special per-provider command initialization logic for OracleCommand
if (cmd is global::Oracle.ManagedDataAccess.Client.OracleCommand cmd0)
{
cmd0.BindByName = true;
cmd0.InitialLONGFetchSize = -1;

}
return cmd;
}

}

private static readonly CommonCommandFactory<object?> DefaultCommandFactory = new();

private sealed class CommandFactory0 : CommonCommandFactory<global::UsersSqlQueries.UserIncrementParams>
{
internal static readonly CommandFactory0 Instance = new();
public override void AddParameters(in global::Dapper.UnifiedCommand cmd, global::UsersSqlQueries.UserIncrementParams args)
{
var ps = cmd.Parameters;
global::System.Data.Common.DbParameter p;
p = cmd.CreateParameter();
p.ParameterName = "userId";
p.DbType = global::System.Data.DbType.Int32;
p.Direction = global::System.Data.ParameterDirection.Input;
p.Value = AsValue(args.UserId);
ps.Add(p);

p = cmd.CreateParameter();
p.ParameterName = "date";
p.DbType = global::System.Data.DbType.Date;
p.Direction = global::System.Data.ParameterDirection.Input;
p.Value = AsValue(args.Date);
ps.Add(p);

}
public override void UpdateParameters(in global::Dapper.UnifiedCommand cmd, global::UsersSqlQueries.UserIncrementParams args)
{
var ps = cmd.Parameters;
ps[0].Value = AsValue(args.UserId);
ps[1].Value = AsValue(args.Date);

}
public override bool CanPrepare => true;

}


}
}
namespace System.Runtime.CompilerServices
{
// this type is needed by the compiler to implement interceptors - it doesn't need to
// come from the runtime itself, though

[global::System.Diagnostics.Conditional("DEBUG")] // not needed post-build, so: evaporate
[global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)]
sealed file class InterceptsLocationAttribute : global::System.Attribute
{
public InterceptsLocationAttribute(string path, int lineNumber, int columnNumber)
{
_ = path;
_ = lineNumber;
_ = columnNumber;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generator produced 1 diagnostics:

Hidden DAP000 L1 C1
Dapper.AOT handled 1 of 1 possible call-sites using 1 interceptors, 1 commands and 0 readers
4 changes: 4 additions & 0 deletions test/Dapper.AOT.Test/Interceptors/DbValueUsage.output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generator produced 1 diagnostics:

Hidden DAP000 L1 C1
Dapper.AOT handled 1 of 1 possible call-sites using 1 interceptors, 1 commands and 0 readers
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public override void AddParameters(in global::Dapper.UnifiedCommand cmd, global:
global::System.Data.Common.DbParameter p;
p = cmd.CreateParameter();
p.ParameterName = "f";
p.DbType = global::System.Data.DbType.String;
p.DbType = global::System.Data.DbType.AnsiString;
p.Size = 200;
p.Direction = global::System.Data.ParameterDirection.Input;
p.Value = AsValue(args.B);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public override void AddParameters(in global::Dapper.UnifiedCommand cmd, global:
global::System.Data.Common.DbParameter p;
p = cmd.CreateParameter();
p.ParameterName = "f";
p.DbType = global::System.Data.DbType.String;
p.DbType = global::System.Data.DbType.AnsiString;
p.Size = 200;
p.Direction = global::System.Data.ParameterDirection.Input;
p.Value = AsValue(args.B);
Expand Down

0 comments on commit 643477a

Please sign in to comment.