From a4e34b02f2afc1fb07d51db8fbf76e4f2fb1c4e1 Mon Sep 17 00:00:00 2001 From: alatanza <160479234+alatanza@users.noreply.github.com> Date: Sat, 12 Oct 2024 11:36:55 +0200 Subject: [PATCH] fix: properly handle value types when setting properties on dynamic objects returned by Dapper queries --- Dapper/SqlMapper.DapperRowMetaObject.cs | 2 +- tests/Dapper.Tests/MiscTests.cs | 42 +++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Dapper/SqlMapper.DapperRowMetaObject.cs b/Dapper/SqlMapper.DapperRowMetaObject.cs index 75e7a15a6..7b5350dfb 100644 --- a/Dapper/SqlMapper.DapperRowMetaObject.cs +++ b/Dapper/SqlMapper.DapperRowMetaObject.cs @@ -81,7 +81,7 @@ public override System.Dynamic.DynamicMetaObject BindSetMember(System.Dynamic.Se var parameters = new System.Linq.Expressions.Expression[] { System.Linq.Expressions.Expression.Constant(binder.Name), - value.Expression, + System.Linq.Expressions.Expression.Convert(value.Expression, typeof(object)), }; var callMethod = CallMethod(setValueMethod, parameters); diff --git a/tests/Dapper.Tests/MiscTests.cs b/tests/Dapper.Tests/MiscTests.cs index 1bf4bbfb0..9323be671 100644 --- a/tests/Dapper.Tests/MiscTests.cs +++ b/tests/Dapper.Tests/MiscTests.cs @@ -1309,9 +1309,9 @@ public HazGetOnlyAndCtor(int idProperty, string nameProperty) IdProperty = idProperty; NameProperty = nameProperty; } - } - - [Fact] + } + + [Fact] public void Issue1164_OverflowExceptionForByte() { const string sql = "select cast(200 as smallint) as [value]"; // 200 more than sbyte.MaxValue but less than byte.MaxValue @@ -1358,5 +1358,41 @@ public async Task QuerySplitStruct() // https://github.com/DapperLib/Dapper/issu Assert.Single(results); } + + [Fact] + public void SetDynamicProperty_WithReferenceType_Succeeds() + { + var obj = connection.QueryFirst("select 1 as ExistingProperty"); + + obj.ExistingProperty = "foo"; + Assert.Equal("foo", (string)obj.ExistingProperty); + + obj.NewProperty = new Uri("http://example.net/"); + Assert.Equal(new Uri("http://example.net/"), (Uri)obj.NewProperty); + } + + [Fact] + public void SetDynamicProperty_WithBoxedValueType_Succeeds() + { + var obj = connection.QueryFirst("select 'foo' as ExistingProperty"); + + obj.ExistingProperty = (object)1; + Assert.Equal(1, (int)obj.ExistingProperty); + + obj.NewProperty = (object)true; + Assert.True(obj.NewProperty); + } + + [Fact] + public void SetDynamicProperty_WithValueType_Succeeds() + { + var obj = connection.QueryFirst("select 'foo' as ExistingProperty"); + + obj.ExistingProperty = 1; + Assert.Equal(1, (int)obj.ExistingProperty); + + obj.NewProperty = true; + Assert.True(obj.NewProperty); + } } }