Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit e1bf81e

Browse files
committed
Use Type Converters for converting Scalar values
1 parent 3c66834 commit e1bf81e

File tree

6 files changed

+93
-36
lines changed

6 files changed

+93
-36
lines changed

src/ServiceStack.OrmLite.Sqlite/Converters/SqliteDateTimeConverter.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,14 @@ public override object GetValue(IDataReader reader, int columnIndex)
6767
}
6868
catch (Exception ex)
6969
{
70-
var dateStr = reader.GetString(columnIndex);
70+
var value = reader.GetValue(columnIndex);
71+
if (value == DBNull.Value)
72+
return null;
73+
74+
var dateStr = value as string;
75+
if (dateStr == null)
76+
throw new Exception("Converting from {0} to DateTime is not supported".Fmt(value.GetType().Name));
77+
7178
Log.Warn("Error reading string as DateTime in Sqlite: " + dateStr, ex);
7279
return DateTime.Parse(dateStr);
7380
}

src/ServiceStack.OrmLite/Async/OrmLiteReadCommandExtensionsAsync.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ internal static Task<T> ScalarFmtAsync<T>(this IDbCommand dbCmd, CancellationTok
239239
internal static Task<T> ScalarAsync<T>(this IDataReader reader, IOrmLiteDialectProvider dialectProvider, CancellationToken token)
240240
{
241241
return dialectProvider.ReaderRead(reader, () =>
242-
OrmLiteReadCommandExtensions.ToScalar<T>(dialectProvider, reader.GetValue(0)), token);
242+
OrmLiteReadCommandExtensions.ToScalar<T>(dialectProvider, reader), token);
243243
}
244244

245245
public static Task<long> LongScalarAsync(this IDbCommand dbCmd, CancellationToken token)

src/ServiceStack.OrmLite/OrmLiteReadCommandExtensions.cs

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal static IDataReader ExecReader(this IDbCommand dbCmd, string sql)
3737
{
3838
dbCmd.CommandTimeout = OrmLiteConfig.CommandTimeout;
3939
dbCmd.CommandText = sql;
40-
40+
4141
if (Log.IsDebugEnabled)
4242
Log.DebugCommand(dbCmd);
4343

@@ -274,7 +274,7 @@ internal static IDbCommand SetParameters(this IDbCommand dbCmd, object anonType,
274274

275275
internal static IDbCommand SetParameters(this IDbCommand dbCmd, IDictionary<string, object> dict, bool excludeDefaults)
276276
{
277-
if (dict == null)
277+
if (dict == null)
278278
return dbCmd;
279279

280280
dbCmd.Parameters.Clear();
@@ -377,17 +377,17 @@ internal static T Single<T>(this IDbCommand dbCmd, string sql, IEnumerable<IDbDa
377377
{
378378
dbCmd.SetParameters(sqlParams);
379379

380-
return OrmLiteUtils.IsScalar<T>()
381-
? dbCmd.Scalar<T>(sql)
380+
return OrmLiteUtils.IsScalar<T>()
381+
? dbCmd.Scalar<T>(sql)
382382
: dbCmd.ConvertTo<T>(dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql));
383383
}
384384

385385
internal static T Single<T>(this IDbCommand dbCmd, string sql, object anonType)
386386
{
387387
dbCmd.SetParameters<T>(anonType, excludeDefaults: false);
388388

389-
return OrmLiteUtils.IsScalar<T>()
390-
? dbCmd.Scalar<T>(sql)
389+
return OrmLiteUtils.IsScalar<T>()
390+
? dbCmd.Scalar<T>(sql)
391391
: dbCmd.ConvertTo<T>(dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql));
392392
}
393393

@@ -509,7 +509,7 @@ internal static List<T> SelectNonDefaults<T>(this IDbCommand dbCmd, object filte
509509

510510
internal static List<T> SelectNonDefaults<T>(this IDbCommand dbCmd, string sql, object anonType = null)
511511
{
512-
if (anonType != null) dbCmd.SetParameters<T>(anonType, excludeDefaults:true);
512+
if (anonType != null) dbCmd.SetParameters<T>(anonType, excludeDefaults: true);
513513

514514
return dbCmd.ConvertToList<T>(dbCmd.GetDialectProvider().ToSelectStatement(typeof(T), sql));
515515
}
@@ -575,7 +575,7 @@ private static IEnumerable<T> ColumnLazy<T>(this IDbCommand dbCmd, string sql)
575575
if (value == DBNull.Value)
576576
yield return default(T);
577577
else
578-
yield return (T) value;
578+
yield return (T)value;
579579
}
580580
}
581581
}
@@ -655,34 +655,38 @@ internal static T Scalar<T>(this IDataReader reader, IOrmLiteDialectProvider dia
655655
{
656656
while (reader.Read())
657657
{
658-
object oValue = reader.GetValue(0);
659-
return typeof(T) == typeof (object)
660-
? (T)oValue
661-
: ToScalar<T>(dialectProvider, oValue);
658+
return ToScalar<T>(dialectProvider, reader);
662659
}
663660

664661
return default(T);
665662
}
666663

667-
internal static T ToScalar<T>(IOrmLiteDialectProvider dialectProvider, object oValue)
664+
internal static T ToScalar<T>(IOrmLiteDialectProvider dialectProvider, IDataReader reader, int columnIndex = 0)
668665
{
669-
if (oValue == DBNull.Value) return default(T);
666+
var nullableType = Nullable.GetUnderlyingType(typeof(T));
667+
if (nullableType != null)
668+
{
669+
object oValue = reader.GetValue(columnIndex);
670+
if (oValue == DBNull.Value)
671+
return default(T);
672+
}
670673

671-
var typeCode = typeof(T).GetUnderlyingTypeCode();
672-
switch (typeCode)
674+
var underlyingType = nullableType ?? typeof(T);
675+
if (underlyingType == typeof(object))
676+
return (T)reader.GetValue(0);
677+
678+
var converter = dialectProvider.GetConverter(underlyingType);
679+
if (converter != null)
673680
{
674-
case TypeCode.DateTime:
675-
return (T) (object) DateTime.Parse(oValue.ToString(), CultureInfo.CurrentCulture);
676-
case TypeCode.Decimal:
677-
return (T) (object) Decimal.Parse(oValue.ToString(), CultureInfo.CurrentCulture);
678-
case TypeCode.Single:
679-
return (T) (object) System.Single.Parse(oValue.ToString(), CultureInfo.CurrentCulture);
680-
case TypeCode.Double:
681-
return (T) (object) Double.Parse(oValue.ToString(), CultureInfo.CurrentCulture);
681+
object oValue = converter.GetValue(reader, columnIndex);
682+
if (oValue == null || oValue == DBNull.Value)
683+
return default(T);
684+
685+
var convertedValue = converter.FromDbValue(underlyingType, oValue);
686+
return convertedValue == null ? default(T) : (T)convertedValue;
682687
}
683688

684-
object o = dialectProvider.FromDbValue(oValue, typeof(T));
685-
return o == null ? default(T) : (T) o;
689+
return (T)reader.GetValue(0);
686690
}
687691

688692
internal static long LastInsertId(this IDbCommand dbCmd)
@@ -863,10 +867,10 @@ public static long LongScalar(this IDbCommand dbCmd)
863867
internal static long ToLong(object result)
864868
{
865869
if (result is DBNull) return default(long);
866-
if (result is int) return (int) result;
867-
if (result is decimal) return Convert.ToInt64((decimal) result);
868-
if (result is ulong) return (long) Convert.ToUInt64(result);
869-
return (long) result;
870+
if (result is int) return (int)result;
871+
if (result is decimal) return Convert.ToInt64((decimal)result);
872+
if (result is ulong) return (long)Convert.ToUInt64(result);
873+
return (long)result;
870874
}
871875

872876
internal static T LoadSingleById<T>(this IDbCommand dbCmd, object value)
@@ -941,8 +945,8 @@ public static FieldDefinition GetRefFieldDef(this ModelDefinition modelDef, Mode
941945

942946
public static FieldDefinition GetRefFieldDefIfExists(this ModelDefinition modelDef, ModelDefinition refModelDef)
943947
{
944-
var refField =
945-
refModelDef.FieldDefinitions.FirstOrDefault(x => x.ForeignKey != null && x.ForeignKey.ReferenceType == modelDef.ModelType
948+
var refField =
949+
refModelDef.FieldDefinitions.FirstOrDefault(x => x.ForeignKey != null && x.ForeignKey.ReferenceType == modelDef.ModelType
946950
&& modelDef.IsRefField(x))
947951
?? refModelDef.FieldDefinitions.FirstOrDefault(x => x.ForeignKey != null && x.ForeignKey.ReferenceType == modelDef.ModelType)
948952
?? refModelDef.FieldDefinitions.FirstOrDefault(modelDef.IsRefField);
@@ -976,7 +980,7 @@ public static IDbDataParameter CreateParam(this IDbCommand dbCmd,
976980
string name,
977981
object value = null,
978982
ParameterDirection direction = ParameterDirection.Input,
979-
DbType? dbType=null)
983+
DbType? dbType = null)
980984
{
981985
var p = dbCmd.CreateParameter();
982986
var dialectProvider = dbCmd.GetDialectProvider();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace ServiceStack.OrmLite.Tests.Issues
5+
{
6+
[TestFixture]
7+
public class SelectScalarTests : OrmLiteTestBase
8+
{
9+
public class TestPerson
10+
{
11+
public Guid Id { get; set; }
12+
public long Long { get; set; }
13+
public float Float { get; set; }
14+
public double Double { get; set; }
15+
public decimal Decimal { get; set; }
16+
}
17+
18+
[Test]
19+
public void Should_Return_Scalar_Value()
20+
{
21+
using (var db = OpenDbConnection())
22+
{
23+
db.DropAndCreateTable<TestPerson>();
24+
25+
var row = new TestPerson
26+
{
27+
Id = Guid.NewGuid(),
28+
Long = 1,
29+
Decimal = 1.1M,
30+
Double = 1.1,
31+
Float = 1.1f,
32+
};
33+
db.Insert(row);
34+
35+
var q = db.From<TestPerson>().Where(x => x.Id == row.Id);
36+
37+
Assert.That(db.Scalar<Guid>(q.Select(x => x.Id)), Is.EqualTo(row.Id));
38+
Assert.That(db.Scalar<long>(q.Select(x => x.Long)), Is.EqualTo(row.Long));
39+
Assert.That(db.Scalar<decimal>(q.Select(x => x.Decimal)), Is.EqualTo(row.Decimal));
40+
Assert.That(db.Scalar<double>(q.Select(x => x.Double)), Is.EqualTo(row.Double));
41+
Assert.That(db.Scalar<float>(q.Select(x => x.Float)), Is.EqualTo(row.Float));
42+
}
43+
}
44+
}
45+
}

tests/ServiceStack.OrmLite.Tests/OrmLiteGetScalarTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void Can_get_scalar_value()
7171
r2 = db.Scalar<Author, DateTime?>(
7272
e => Sql.Max(e.LastActivity),
7373
e => e.City == "Bogota");
74-
Assert.That(expectedNullableDate, Is.EqualTo(r2));
74+
Assert.That(r2, Is.EqualTo(expectedNullableDate));
7575

7676
r2 = db.Scalar<Author, DateTime?>(e => Sql.Max(e.LastActivity), e => e.City == "SinCity");
7777
Assert.That(default(DateTime?), Is.EqualTo(r2));

tests/ServiceStack.OrmLite.Tests/ServiceStack.OrmLite.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
<Compile Include="Issues\LoadReferencesCaseSensitiveTest.cs" />
144144
<Compile Include="Issues\LoadSelectIssue.cs" />
145145
<Compile Include="Issues\MultipleSelfJoinsWithNullableInts.cs" />
146+
<Compile Include="Issues\SelectScalarTests.cs" />
146147
<Compile Include="Issues\UtcDateTimeIssueTests.cs" />
147148
<Compile Include="Issues\JoinsWithSchemas.cs" />
148149
<Compile Include="Issues\MappingFieldsFromStoredProcedureTests.cs" />

0 commit comments

Comments
 (0)