New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
System.InvalidCastException - Dapper 1.50.4 #1001
Comments
And this (sqlite) is why we can't have nice things :) Basically, the sqlite provider lies to us - or rather: it has a very limited selection of data types, and it does the best it can to guess what the actual data type is, based on the declared SQLite datatype and the data it knows about at the time. What dapper wants to do, for performance is: using(var reader = ExecuteQuery(...))
{
// for each grid:
Func<DataReader, T> materializer = InspectReaderSchemaAndGetMaterializer<T>(reader);
while(reader.Read()) {
var model = materializer(reader);
// ...do something with model
}
} Unfortunately, SQLite changes its mind abut what the schema is per row. This is ... to put it mildly, "inconvenient". It might thing that a column is going to be a We have two choices here, to compensate for SQLite's indecisiveness:
Both have performance implications. So: that's the "why". As for fixing it: my preference is probably on the second option, because simply querying the schema is horribly expensive. It just needs a huge rewrite of some very complex IL-generation code :) |
I was able to work around this with a wrapper type and an implementation of public class Startup {
public void OnStartup() {
// register type handler
SqlMapper.AddTypeHandler(typeof(DbDecimal), new DbDecimalTypeHandler ());
}
}
public class Foo
{
// use wrapper type instead of decimal
// public decimal? Value { get; set; }
public DbDecimal? Value { get; set; }
}
public struct DbDecimal
{
public static implicit operator decimal(DbDecimalv) => v.Value ;
public static implicit operator DbDecimal(decimal v) => new DbDecimal(v);
public decimal Value { get; set; }
public DbDecimal(decimal? v) => Value = v;
}
internal class DbDecimalTypeHandler : SqlMapper.ITypeHandler
{
public void SetValue(IDbDataParameter parameter, object value)
{
parameter.Value = value;
}
public object Parse(Type destinationType, object value)
{
if(value == DBNull.Value || value == null)
return null;
switch(value)
{
case decimal decimalValue:
return new DbDecimal(decimalValue);
case int intValue:
return new DbDecimal(Convert.ToDecimal(intValue));
case double doubleValue:
return new DbDecimal(Convert.ToDecimal(doubleValue));
default:
throw new DataException();
}
}
} |
Hi, I'm having similar invalid cast issue and I did a similar wrapper class. What I'd like to know is if I'm able to replace the 'default' type handlers in Dapper? I tried doing SqlMapper.RemoveTypeMap(typeof(Int32); and then SqlMapper.AddTypeHandler(typeof(Int32), new Int32Handler()); but I'm still getting invalid cast, it's as if the RemoveTypeMap() isn't having any effect. Much appreciated, |
@kyledarrenhanson If you call |
@NickCraver much appreciated but I still can't seem to make it work. below is some of the code I've been trying, some of which is commented out, but shows you things I've been attempting:
// SqlMapper.AddTypeHandler(typeof(TinyInt), new TinyIntHandler());
at this point on the query, it fails with: my type handler:internal class Int32Handler : SqlMapper.ITypeHandler public void SetValue(IDbDataParameter parameter, object value) |
It's worth mentioning that people are likely to run into this during an empty when there are null values for columns that aren't of type The simplest solution, of course is to set those values to |
Was this ever resolved? I solved this issue @ #1002 (comment) for those who are having this problem. |
We are evaluating Dapper for use as a SQLite micro ORM and we have hit up against this issue when querying nullable INTEGER columns. Are there plans to fix this in the near future? We would rather not start off writing type handlers for such a common use case in our domain. @mgravell posted the following on this issue some time ago:
|
I was able to solve issue by adding custom mapper for Int32
|
Dec 2020, still has this problem. |
My team and I have discovered what seems to be a bug in Dapper v1.50.4
Exception thrown: 'System.InvalidCastException' in Dapper.dll
Exception thrown: 'System.Data.DataException' in Dapper.dll
The bug is simple, if a field (INT for example) is created and if the first value inserted into this field is Null and the second value inserted is an INT. The program will crash unless than value is cast to the correct type.
This program has been built to show how to duplicate the issue:
https://github.com/rhfrench/DapperTest
We were also having trouble nullable int values even when the values are cast to the correct type. The first image is the actual error I'm running into. The second image shows the output of the query that is being run. We are using Microsoft.Data.Sqlite 2.0.1.
Here is the class:
The text was updated successfully, but these errors were encountered: