Skip to content

Commit

Permalink
Add support for parsing IDs from decimals to dapper (#120)
Browse files Browse the repository at this point in the history
* Add basic support for parsing decimal as IDs in Dapper

Fixes #118

* Explicitly test decimal conversion with Sqlserver
  • Loading branch information
andrewlock committed Dec 1, 2023
1 parent e386666 commit e53602c
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/StronglyTypedIds.Templates/int-dapper.typedid
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
return value switch
{
int intValue => new PLACEHOLDERID(intValue),
long longValue when longValue < int.MaxValue => new PLACEHOLDERID((int)longValue),
short shortValue => new PLACEHOLDERID(shortValue),
long longValue and < int.MaxValue and > int.MinValue => new PLACEHOLDERID((int)longValue),
decimal decimalValue and < int.MaxValue and > int.MinValue => new PLACEHOLDERID((int)decimalValue),
string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result),
_ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"),
};
Expand Down
4 changes: 3 additions & 1 deletion src/StronglyTypedIds.Templates/int-full.typedid
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@
return value switch
{
int intValue => new PLACEHOLDERID(intValue),
long longValue when longValue < int.MaxValue => new PLACEHOLDERID((int)longValue),
short shortValue => new PLACEHOLDERID(shortValue),
long longValue and < int.MaxValue and > int.MinValue => new PLACEHOLDERID((int)longValue),
decimal decimalValue and < int.MaxValue and > int.MinValue => new PLACEHOLDERID((int)decimalValue),
string stringValue when !string.IsNullOrEmpty(stringValue) && int.TryParse(stringValue, out var result) => new PLACEHOLDERID(result),
_ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"),
};
Expand Down
1 change: 1 addition & 0 deletions src/StronglyTypedIds.Templates/long-dapper.typedid
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
long longValue => new PLACEHOLDERID(longValue),
int intValue => new PLACEHOLDERID(intValue),
short shortValue => new PLACEHOLDERID(shortValue),
decimal decimalValue and < long.MaxValue and > long.MinValue => new PLACEHOLDERID((long)decimalValue),
string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result),
_ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"),
};
Expand Down
1 change: 1 addition & 0 deletions src/StronglyTypedIds.Templates/long-full.typedid
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@
long longValue => new PLACEHOLDERID(longValue),
int intValue => new PLACEHOLDERID(intValue),
short shortValue => new PLACEHOLDERID(shortValue),
decimal decimalValue and < long.MaxValue and > long.MinValue => new PLACEHOLDERID((long)decimalValue),
string stringValue when !string.IsNullOrEmpty(stringValue) && long.TryParse(stringValue, out var result) => new PLACEHOLDERID(result),
_ => throw new global::System.InvalidCastException($"Unable to cast object of type {value.GetType()} to PLACEHOLDERID"),
};
Expand Down
1 change: 1 addition & 0 deletions test/IntegrationLibraries.props
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="Dapper" Version="2.0.90" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
22 changes: 22 additions & 0 deletions test/StronglyTypedIds.IntegrationTests/IntIdTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
Expand Down Expand Up @@ -282,6 +283,27 @@ public async Task WhenDapperValueConverterUsesValueConverter()
Assert.Equal(new ConvertersIntId(123), value);
}

[Fact(Skip = "Requires localdb to be available")]
public async Task WhenDapperValueConverterUsesValueConverterWithSqlServer()
{
using var connection = new SqlConnection("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True;Connect Timeout=30");
await connection.OpenAsync();

var results = await connection.QueryAsync<ConvertersIntId>("SELECT CAST (123 AS numeric(38,0))");

var value = Assert.Single(results);
Assert.Equal(new ConvertersIntId(123), value);
}

[Fact]
public void WhenDapperValueConverterAndDecimalUsesValueConverter()
{
var handler = new ConvertersIntId.DapperTypeHandler();
var value = handler.Parse((decimal) 123L);

Assert.Equal(new ConvertersIntId(123), value);
}

[Theory]
[InlineData(123)]
[InlineData("123")]
Expand Down
22 changes: 22 additions & 0 deletions test/StronglyTypedIds.IntegrationTests/LongIdTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlClient;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
Expand Down Expand Up @@ -294,6 +295,27 @@ public async Task WhenDapperValueConverterUsesValueConverter()
Assert.Equal(value, new ConvertersLongId(123));
}

[Fact(Skip = "Requires localdb to be available")]
public async Task WhenDapperValueConverterUsesValueConverterWithSqlServer()
{
using var connection = new SqlConnection("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True;Connect Timeout=30");
await connection.OpenAsync();

var results = await connection.QueryAsync<ConvertersIntId>("SELECT CAST (123 AS numeric(38,0))");

var value = Assert.Single(results);
Assert.Equal(new ConvertersIntId(123), value);
}

[Fact]
public void WhenDapperValueConverterAndDecimalUsesValueConverter()
{
var handler = new ConvertersLongId.DapperTypeHandler();
var value = handler.Parse((decimal) 123L);

Assert.Equal(new ConvertersLongId(123), value);
}

#if NET6_0_OR_GREATER
[Fact]
public void WhenConventionBasedEfCoreValueConverterUsesValueConverter()
Expand Down

0 comments on commit e53602c

Please sign in to comment.