Skip to content

Commit a18dc63

Browse files
sebastienrosmgravell
authored andcommitted
Use InvariantCulture in FlexibleConvert (#1363)
In Sqlite, DateTime is stored as String, and custom serializers ultimately use Convert.ChangeType to do the conversion. The generated code however doesn't set the Invariant culture, and the conversion can fail if the current culture doesn't match the standard DateTime serialization format from Sqlite.
1 parent 247e498 commit a18dc63

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

Dapper.Tests/Providers/SqliteTests.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Data.Common;
44
using System.Linq;
5+
using System.Threading;
56
using System.Threading.Tasks;
67
using Xunit;
78

@@ -123,6 +124,46 @@ private void Isse467_SqliteParameterNaming(bool prefix)
123124
var i = Convert.ToInt32(cmd.ExecuteScalar());
124125
Assert.Equal(42, i);
125126
}
126-
}
127+
}
128+
129+
[FactSqlite]
130+
public void DateTimeIsParsedWithInvariantCulture()
131+
{
132+
connection.Execute("CREATE TABLE [PersonWithDob] ([Id] integer primary key autoincrement, [DoB] DATETIME not null )");
133+
134+
var localMorning = DateTime.Parse("2019-07-31 01:00:00");
135+
136+
var culture = Thread.CurrentThread.CurrentCulture;
137+
138+
try
139+
{
140+
connection.Execute("INSERT INTO [PersonWithDob] ([DoB]) VALUES (@DoB)", new PersonWithDob { DoB = localMorning });
141+
142+
// Before we read the column, use Farsi this is a way to ensure the
143+
// InvariantCulture is used as otherwise it would fail because Farsi
144+
// is not able to parse a DateTime that is formatted with Invariant
145+
146+
var farsi = System.Globalization.CultureInfo.GetCultureInfo("fa-IR");
147+
Thread.CurrentThread.CurrentCulture = farsi;
148+
Thread.CurrentThread.CurrentUICulture = farsi;
149+
150+
var person = connection.QueryFirst<PersonWithDob>("SELECT * FROM [PersonWithDob]");
151+
152+
Assert.Equal(localMorning, person.DoB);
153+
}
154+
finally
155+
{
156+
Thread.CurrentThread.CurrentCulture = culture;
157+
Thread.CurrentThread.CurrentUICulture = culture;
158+
159+
connection.Execute("DROP TABLE [PersonWithDob]");
160+
}
161+
}
162+
163+
private class PersonWithDob
164+
{
165+
public int Id { get; set; }
166+
public DateTime DoB { get; set; }
167+
}
127168
}
128169
}

Dapper/SqlMapper.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3563,7 +3563,8 @@ private static void FlexibleConvertBoxedFromHeadOfStack(ILGenerator il, Type fro
35633563
{
35643564
il.Emit(OpCodes.Ldtoken, via ?? to); // stack is now [target][target][value][member-type-token]
35653565
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)), null); // stack is now [target][target][value][member-type]
3566-
il.EmitCall(OpCodes.Call, typeof(Convert).GetMethod(nameof(Convert.ChangeType), new Type[] { typeof(object), typeof(Type) }), null); // stack is now [target][target][boxed-member-type-value]
3566+
il.EmitCall(OpCodes.Call, InvariantCulture, null); // stack is now [target][target][value][member-type][culture]
3567+
il.EmitCall(OpCodes.Call, typeof(Convert).GetMethod(nameof(Convert.ChangeType), new Type[] { typeof(object), typeof(Type), typeof(IFormatProvider) }), null); // stack is now [target][target][boxed-member-type-value]
35673568
il.Emit(OpCodes.Unbox_Any, to); // stack is now [target][target][typed-value]
35683569
}
35693570
}

0 commit comments

Comments
 (0)