From 837332bf3a8e4af61493e8617c4b0ef8d9f1ff97 Mon Sep 17 00:00:00 2001 From: Henk Mollema Date: Thu, 28 Mar 2019 14:30:37 +0100 Subject: [PATCH] Fix matching nullable properties in convetions Resolves #82 --- .../Conventions/Convention.cs | 15 ++++-- .../Dapper.FluentMap.Tests/ConventionTests.cs | 53 +++++++++++++++++++ test/Dapper.FluentMap.Tests/TestEntity.cs | 2 + 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/Dapper.FluentMap/Conventions/Convention.cs b/src/Dapper.FluentMap/Conventions/Convention.cs index 39ddd33..feb66ca 100644 --- a/src/Dapper.FluentMap/Conventions/Convention.cs +++ b/src/Dapper.FluentMap/Conventions/Convention.cs @@ -42,9 +42,18 @@ protected PropertyConventionConfiguration Properties() /// A configuration object for the convention. protected PropertyConventionConfiguration Properties() { - // Get the underlying type for a nullale type. (int? -> int) - var underlyingType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); - var config = new PropertyConventionConfiguration().Where(p => p.PropertyType == underlyingType); + var type = typeof(T); + PropertyConventionConfiguration config; + if (Nullable.GetUnderlyingType(type) != null) + { + // Convention defined for nullable type, match nullable properties + config = new PropertyConventionConfiguration().Where(p => p.PropertyType == type); + } + else + { + // Convention defined for non-nullable types, match both nullabel and non-nullable properties + config = new PropertyConventionConfiguration().Where(p => (Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType) == type); + } ConventionConfigurations.Add(config); return config; diff --git a/test/Dapper.FluentMap.Tests/ConventionTests.cs b/test/Dapper.FluentMap.Tests/ConventionTests.cs index 0233301..0ecf735 100644 --- a/test/Dapper.FluentMap.Tests/ConventionTests.cs +++ b/test/Dapper.FluentMap.Tests/ConventionTests.cs @@ -37,6 +37,41 @@ public void DerivedProperties() Assert.Equal(typeof(DerivedTestEntity).GetProperty(nameof(TestEntity.Id)), colId.Property); } + [Fact] + public void NullableProperties() + { + // Arrange + FluentMapper.Initialize(c => c.AddConvention().ForEntity()); + var typeMap = SqlMapper.GetTypeMap(typeof(TestEntity)); + + // Act + var colValue = typeMap.GetMember("intId"); + var colValueNotNull = typeMap.GetMember("intOtherId"); + + //Assert + Assert.NotNull(colValue); + Assert.NotNull(colValueNotNull); + Assert.Equal(typeof(TestEntity).GetProperty(nameof(TestEntity.Id)), colValue.Property); + Assert.Equal(typeof(TestEntity).GetProperty(nameof(TestEntity.OtherId)), colValueNotNull.Property); + } + + [Fact] + public void ExplicitNullableProperties() + { + // Arrange + FluentMapper.Initialize(c => c.AddConvention().ForEntity()); + var typeMap = SqlMapper.GetTypeMap(typeof(TestEntityWithNullable)); + + // Act + var colValue = typeMap.GetMember("decValue"); + var colValueNotNull = typeMap.GetMember("decValueNotNull"); + + //Assert + Assert.NotNull(colValue); + Assert.Null(colValueNotNull); + Assert.Equal(typeof(TestEntityWithNullable).GetProperty(nameof(TestEntityWithNullable.Value)), colValue.Property); + } + [Fact] public void TwoEntitiesWithSamePropertyName() { @@ -84,6 +119,24 @@ public TestConvention() } } + private class NullableConvention : Convention + { + public NullableConvention() + { + Properties() + .Configure(c => c.HasPrefix("int")); + } + } + + private class ExplicitNullableConvention : Convention + { + public ExplicitNullableConvention() + { + Properties() + .Configure(c => c.HasPrefix("dec")); + } + } + private class DerivedConvention : Convention { public DerivedConvention() diff --git a/test/Dapper.FluentMap.Tests/TestEntity.cs b/test/Dapper.FluentMap.Tests/TestEntity.cs index cfdc63c..8f4e264 100644 --- a/test/Dapper.FluentMap.Tests/TestEntity.cs +++ b/test/Dapper.FluentMap.Tests/TestEntity.cs @@ -3,6 +3,8 @@ namespace Dapper.FluentMap.Tests public class TestEntity { public int Id { get; set; } + + public int? OtherId { get; set; } } public class TestEntityWithNullable