SqlMapperExtensions doesn't honor SqlMapper.TypeHandler in autogenerated primery keys when Inserting in Sql Server
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 48/100
Research direction
The failing path is SqlServerAdapter.Insert in SqlMapperExtensions.cs, especially the generated-key assignment shown around line 834; start by reproducing the sample with Key and KeyTypeHandler. Done means inserting an entity with a custom key type no longer throws and the generated key is assigned correctly.
Written by the indexing model from the issue text.
Description
SqlMapper.TypeHandler is intended to support custom types in entities. It's documented here:
https://medium.com/dapper-net/custom-type-handling-4b447b97c620
(I'm not sure if that is official documentation or not)
But Dapper.Contrib does not honor that. It throws an System.InvalidCastException in line 834 in SqlMapperExtensions:
public int Insert(IDbConnection connection, IDbTransaction transaction, int? commandTimeout, string tableName, string columnList, string parameterList, IEnumerable<PropertyInfo> keyProperties, object entityToInsert)
{
var cmd = $"insert into {tableName} ({columnList}) values ({parameterList});select SCOPE_IDENTITY() id";
var multi = connection.QueryMultiple(cmd, entityToInsert, transaction, commandTimeout);
var first = multi.Read().FirstOrDefault();
if (first == null || first.id == null) return 0;
var id = (int)first.id;
var propertyInfos = keyProperties as PropertyInfo[] ?? keyProperties.ToArray();
if (propertyInfos.Length == 0) return id;
var idProperty = propertyInfos[0];
idProperty.SetValue(entityToInsert, Convert.ChangeType(id, idProperty.PropertyType), null);
return id;
}
Exception
System.InvalidCastException: Invalid cast from 'System.Int32' to 'DapperInsertKey.Program+Key'.
at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
at SqlServerAdapter.Insert(IDbConnection connection, IDbTransaction transaction, Nullable`1 commandTimeout, String tableName, String columnList, String parameterList, IEnumerable`1 keyProperties, Object entityToInsert) in /_/Dapper.Contrib/SqlMapperExtensions.cs:line 834
at Dapper.Contrib.Extensions.SqlMapperExtensions.Insert[T](IDbConnection connection, T entityToInsert, IDbTransaction transaction, Nullable`1 commandTimeout) in /_/Dapper.Contrib/SqlMapperExtensions.cs:line 377
at DapperInsertKey.Program.Main(String[] args) in D:\users\yecarri\source\repos\DapperInsertKey\DapperInsertKey\Program.cs:line 31
Code
using Dapper;
using Dapper.Contrib.Extensions;
using Microsoft.Data.SqlClient;
using System.Data;
namespace DapperInsertKey
{
internal class Program
{
static void Main(string[] args)
{
SqlMapper.AddTypeHandler(new KeyTypeHandler());
using (var connection = new SqlConnection("server=.;database=equus;integrated security=true;Encrypt=false"))
{
connection.Open();
connection.Execute(@"
If not exists (select TABLE_NAME from information_schema.TABLES t
where t.TABLE_SCHEMA='dbo' AND TABLE_NAME= 'User')
CREATE TABLE dbo.[User](
UserId int identity(1,1) primary key clustered,
[UserName] [varchar](120) NOT NULL
)");
connection.Execute("TRUNCATE TABLE dbo.[User]");
var user = new User() { UserName="OSO" };
connection.Insert(user);
connection.Close();
}
}
public struct Key
{
private readonly int _value;
public Key(int value) { _value = value; }
public static implicit operator Key(int value) { return new Key(value); }
public static implicit operator int(Key key) { return key._value; }
}
[Table("dbo.[User]")]
public class User
{
[Key]
public Key UserId { get; set; }
public string UserName { get; set; } = "";
}
public class KeyTypeHandler : SqlMapper.TypeHandler<Key>
{
public override Key Parse(object value)
{
return new Key((int)value);
}
public override void SetValue(IDbDataParameter parameter, Key value)
{
parameter.Value = (int)value;
}
}
}
}
- Dominant language
- C#
- Stars
- 293
- Forks
- 109
- PR merge metrics
- No merged PRs in 30d
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from DapperLib/Dapper.Contrib
-
Difficulty 1/5 Under an hour Newbie friendliness 75/100
DapperLib/Dapper.Contrib#22 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 42/100
DapperLib/Dapper.Contrib#174 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
DapperLib/Dapper.Contrib#173 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 10/100
DapperLib/Dapper.Contrib#172 · 1 comment · 4 reactions ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
DapperLib/Dapper.Contrib#165 ·
All issues in DapperLib/Dapper.Contrib
Similar issues
-
type/automation type/tech-debt
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
t/bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
ci-failure-cause test-failure
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
area:auth FE mvp P3
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
klasolsson81/jobbliggaren#1788 ·