DapperQueryBuilder icon indicating copy to clipboard operation
DapperQueryBuilder copied to clipboard

Interfaces as properties are not working as expected

Open dittodhole opened this issue 3 years ago • 2 comments

Hi there!

Following DTO given:

public interface IFoo { }
public sealed record FooA : IFoo { }
public sealed record FooB : IFoo { }

public sealed record DTO
{
  public int Id { get; set; }
  public IFoo? Foo { get; set; }
}

And the following query:

SqlMapper.AddTypeHandler(SqlMapper.StringTypeHandler<IFoo> _);

var dto = new DTO
{
  Foo = new FooA()
};

using var dbConnection = _;

dbConnection.Open();

var commandBuilder = dbConnection.CommandBuiler($@"
INSERT INTO [DTO] ([Id], [Foo])
VALUES (@Id, @Foo);");

commandBuilder.AddObjectProperties(dto);

commandBuilder.Execute();

Despite having a custom type handler registered, you'll end up with with:

System.NotSupportedException
  HResult=0x80131515
  Message=The member Foo of type FooA cannot be used as a parameter value
  Source=Dapper
  StackTrace:
   at Dapper.SqlMapper.LookupDbType(Type type, String name, Boolean demand, ITypeHandler& handler) in /_/Dapper/SqlMapper.cs:line 426

Executing this with the original ExecuteAsync works like a charm:

SqlMapper.AddTypeHandler(SqlMapper.StringTypeHandler<IFoo> _);

var dto = new DTO
{
  Foo = new FooA()
};

using var dbConnection = _;

dbConnection.Open();

dbConnection.Execute($@"
INSERT INTO [DTO] ([Id], [Foo])
VALUES (@Id, @Foo);",
  dto);

Any thoughts?

Best Andreas

dittodhole avatar May 24 '22 14:05 dittodhole

Well ... shot too fast 😬

I'll stick to the vanilla approach, as this request seems out of scope.

Use the right tool for the right job.

Best Andreas

dittodhole avatar May 24 '22 15:05 dittodhole

I feel that we should be supporting custom TypeHandlers. Reopening in case someone volunteers to add support for that.

Drizin avatar Jun 03 '22 23:06 Drizin