Closed GoogleCodeExporter closed 9 years ago
I had a look around your source code and it looks like the changes would happen
in GetClassDeserializer.
My IL code skills aren't up to making the changes myself but this is how I
imagine you could do it:
1. For properties and fields that are primitive, add a check whether the value
type is equal to property/field type
2. Values that don't equal the field property/type then are passed to
Convert.ChangeType to convert the value and then use that in the call to the
setter.
Original comment by james.ne...@gmail.com
on 27 May 2011 at 4:42
The problem I have with this is that the overhead of checking the type for
every cell is an unnecessary overhead. In my mind (and consistent with several
ORMs) - the ideal fix here is simply: "get your data right". If the db column
is a byte (tinyint), model it as such in you model. This enforces consistent
data.
Where that is not possible, dapper also supports private properties - so you
can add a property of the "other" type, which can exist purely for the purpose
of acting as a shim between the layers. One final fix, of course, is to CAST at
the SQL.
The one case I can get behind this is with enums; in part to be consistent with
LINQ-to-SQL, which allows text types to map to enum properties. This is
attractive because:
- it is tightly scoped; we know in advance if the property is an enum, so it
doesn't affect every cell
- it is cheap to test (unlike numeric conversions, an "is this a string" test
can be done with the "isinst" opcode, which is exceptionally cheap
Original comment by marc.gravell
on 1 Jun 2011 at 9:21
If you're concerned about performance, what about an attribute to mark up
properties that typed checking and conversion occurs on. I brought up
attributes and type converting here -
http://code.google.com/p/dapper-dot-net/issues/detail?id=24
That way performance is good by default but if you want control over how
strongly typed objects are mapped then you have that control.
(FYI I've already solved this problem myself by having Dapper.Net spit out a
dynamic object and then I have a light-weight reflection based object mapper
over the top of it. I didn't want to go messing around with your IL!)
Original comment by james.ne...@gmail.com
on 1 Jun 2011 at 9:38
Fixed for string => enums; I kinda disagree with the rest. If that is
essential, it would need to be contrib
Original comment by marc.gravell
on 1 Jun 2011 at 10:39
How about byte/int to enum?
Original comment by jimitndi...@gmail.com
on 15 Nov 2011 at 10:09
It does; **if** your enum is a byte, and your data is a byte (tinyint) it will
work as you expect. Likewise, if your enum is an int, and so is your data, it
will work as you expect.
Original comment by marc.gravell
on 15 Nov 2011 at 12:33
The data is smallint (short) in the database and I'm getting
InvalidCastExceptions
Original comment by jimitndi...@gmail.com
on 15 Nov 2011 at 2:36
How is the enum defined? If the enum is : short, then it is a bug. If it isn't
: short, then it is expected. (I'll add a test later today to check it is
working)
Original comment by marc.gravell
on 15 Nov 2011 at 5:47
The following (with the exceptions noted) work fine:
public void TestInt16Usage()
{
connection.Query<short>("select cast(42 as smallint)").Single().IsEqualTo((short)42);
connection.Query<short?>("select cast(42 as smallint)").Single().IsEqualTo((short?)42);
connection.Query<short?>("select cast(null as smallint)").Single().IsEqualTo((short?)null);
// hmmm.... these don't work currently... adding TODO
//connection.Query<ShortEnum>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum)42);
//connection.Query<ShortEnum?>("select cast(42 as smallint)").Single().IsEqualTo((ShortEnum?)42);
//connection.Query<ShortEnum?>("select cast(null as smallint)").Single().IsEqualTo((ShortEnum?)null);
var row =
connection.Query<WithInt16Values>(
"select cast(1 as smallint) as NonNullableInt16, cast(2 as smallint) as NullableInt16, cast(3 as smallint) as NonNullableInt16Enum, cast(4 as smallint) as NullableInt16Enum")
.Single();
row.NonNullableInt16.IsEqualTo((short)1);
row.NullableInt16.IsEqualTo((short)2);
row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Three);
row.NullableInt16Enum.IsEqualTo(ShortEnum.Four);
row =
connection.Query<WithInt16Values>(
"select cast(5 as smallint) as NonNullableInt16, cast(null as smallint) as NullableInt16, cast(6 as smallint) as NonNullableInt16Enum, cast(null as smallint) as NullableInt16Enum")
.Single();
row.NonNullableInt16.IsEqualTo((short)5);
row.NullableInt16.IsEqualTo((short?)null);
row.NonNullableInt16Enum.IsEqualTo(ShortEnum.Six);
row.NullableInt16Enum.IsEqualTo((ShortEnum?)null);
}
public class WithInt16Values
{
public short NonNullableInt16 { get; set; }
public short? NullableInt16 { get; set; }
public ShortEnum NonNullableInt16Enum { get; set; }
public ShortEnum? NullableInt16Enum { get; set; }
}
public enum ShortEnum : short
{
Zero = 0, One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6
}
Original comment by marc.gravell
on 15 Nov 2011 at 8:03
Original issue reported on code.google.com by
james.ne...@gmail.com
on 27 May 2011 at 3:44