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

Commit 307d5d5

Browse files
committed
Merge pull request #287 from CaioProiete/add-support-null-params-in-stored-procs
Add support to null parameters in stored procedures (fix issues #245 and #274)
2 parents 55cfe17 + e6ef83a commit 307d5d5

File tree

2 files changed

+99
-16
lines changed

2 files changed

+99
-16
lines changed

src/ServiceStack.OrmLite/OrmLiteReadExtensions.cs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ private static void SetParameters<T>(this IDbCommand dbCmd, object anonType, boo
248248

249249
p.DbType = OrmLiteConfig.DialectProvider.GetColumnDbType(pi.PropertyType);
250250
p.Direction = ParameterDirection.Input;
251-
p.Value = value;
251+
p.Value = value ?? DBNull.Value;
252252
dbCmd.Parameters.Add(p);
253253
}
254254
}
@@ -265,17 +265,22 @@ private static void SetParameters(this IDbCommand dbCmd, Dictionary<string,objec
265265
if (excludeNulls && value == null) continue;
266266
var p = dbCmd.CreateParameter();
267267
p.ParameterName = kvp.Key;
268-
p.DbType = OrmLiteConfig.DialectProvider.GetColumnDbType(value.GetType()); ;
268+
269+
if (value != null)
270+
{
271+
p.DbType = OrmLiteConfig.DialectProvider.GetColumnDbType(value.GetType());
272+
}
273+
269274
p.Direction = ParameterDirection.Input;
270-
p.Value = value;
275+
p.Value = value ?? DBNull.Value;
271276
dbCmd.Parameters.Add(p);
272277
}
273278
}
274279

275280

276281
public static void SetFilters<T>(this IDbCommand dbCmd, object anonType)
277282
{
278-
dbCmd.SetFilters<T>(anonType, false);
283+
dbCmd.SetFilters<T>(anonType, excludeNulls: false);
279284
}
280285

281286
public static void ClearFilters(this IDbCommand dbCmd)
@@ -327,7 +332,7 @@ internal static T QuerySingle<T>(this IDbCommand dbCmd, object anonType)
327332
{
328333
if (IsScalar<T>()) return QueryScalar<T>(dbCmd, anonType);
329334

330-
dbCmd.SetFilters<T>(anonType, true);
335+
dbCmd.SetFilters<T>(anonType, excludeNulls: false);
331336

332337
using (var dbReader = dbCmd.ExecuteReader())
333338
return dbReader.ConvertTo<T>();
@@ -337,7 +342,7 @@ internal static T QuerySingle<T>(this IDbCommand dbCmd, string sql, object anonT
337342
{
338343
if (IsScalar<T>()) return QueryScalar<T>(dbCmd, sql, anonType);
339344

340-
dbCmd.SetParameters<T>(anonType, true);
345+
dbCmd.SetParameters<T>(anonType, excludeNulls: false);
341346
dbCmd.CommandText = OrmLiteConfig.DialectProvider.ToSelectStatement(typeof(T), sql);
342347

343348
using (var dbReader = dbCmd.ExecuteReader())
@@ -368,7 +373,7 @@ internal static List<T> Where<T>(this IDbCommand dbCmd, object anonType)
368373

369374
internal static List<T> Query<T>(this IDbCommand dbCmd, string sql, object anonType = null)
370375
{
371-
if (anonType != null) dbCmd.SetParameters<T>(anonType, true);
376+
if (anonType != null) dbCmd.SetParameters<T>(anonType, excludeNulls: false);
372377
dbCmd.CommandText = OrmLiteConfig.DialectProvider.ToSelectStatement(typeof(T), sql);
373378

374379
using (var dbReader = dbCmd.ExecuteReader())
@@ -379,7 +384,7 @@ internal static List<T> Query<T>(this IDbCommand dbCmd, string sql, object anonT
379384

380385
internal static List<T> Query<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict)
381386
{
382-
if (dict != null) dbCmd.SetParameters(dict, true);
387+
if (dict != null) dbCmd.SetParameters(dict, excludeNulls: false);
383388
dbCmd.CommandText = OrmLiteConfig.DialectProvider.ToSelectStatement(typeof(T), sql);
384389

385390
using (var dbReader = dbCmd.ExecuteReader())
@@ -390,15 +395,15 @@ internal static List<T> Query<T>(this IDbCommand dbCmd, string sql, Dictionary<s
390395

391396
internal static T QueryScalar<T>(this IDbCommand dbCmd, object anonType)
392397
{
393-
dbCmd.SetFilters<T>(anonType, true);
398+
dbCmd.SetFilters<T>(anonType, excludeNulls: false);
394399

395400
using (var dbReader = dbCmd.ExecuteReader())
396401
return GetScalar<T>(dbReader);
397402
}
398403

399404
internal static T QueryScalar<T>(this IDbCommand dbCmd, string sql, object anonType = null)
400405
{
401-
if (anonType != null) dbCmd.SetParameters<T>(anonType, true);
406+
if (anonType != null) dbCmd.SetParameters<T>(anonType, excludeNulls: false);
402407
dbCmd.CommandText = OrmLiteConfig.DialectProvider.ToSelectStatement(typeof(T), sql);
403408

404409
using (var dbReader = dbCmd.ExecuteReader())
@@ -407,7 +412,7 @@ internal static T QueryScalar<T>(this IDbCommand dbCmd, string sql, object anonT
407412

408413
internal static List<T> SqlList<T>(this IDbCommand dbCmd, string sql, object anonType = null)
409414
{
410-
if (anonType != null) dbCmd.SetParameters<T>(anonType, true);
415+
if (anonType != null) dbCmd.SetParameters<T>(anonType, excludeNulls: false);
411416
dbCmd.CommandText = sql;
412417

413418
using (var dbReader = dbCmd.ExecuteReader())
@@ -418,7 +423,7 @@ internal static List<T> SqlList<T>(this IDbCommand dbCmd, string sql, object ano
418423

419424
internal static List<T> SqlList<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict)
420425
{
421-
if (dict != null) dbCmd.SetParameters(dict, true);
426+
if (dict != null) dbCmd.SetParameters(dict, excludeNulls: false);
422427
dbCmd.CommandText = sql;
423428

424429
using (var dbReader = dbCmd.ExecuteReader())
@@ -429,7 +434,7 @@ internal static List<T> SqlList<T>(this IDbCommand dbCmd, string sql, Dictionary
429434

430435
internal static T SqlScalar<T>(this IDbCommand dbCmd, string sql, object anonType = null)
431436
{
432-
if (anonType != null) dbCmd.SetParameters<T>(anonType, true);
437+
if (anonType != null) dbCmd.SetParameters<T>(anonType, excludeNulls: false);
433438
dbCmd.CommandText = sql;
434439

435440
using (var dbReader = dbCmd.ExecuteReader())
@@ -438,7 +443,7 @@ internal static T SqlScalar<T>(this IDbCommand dbCmd, string sql, object anonTyp
438443

439444
internal static T SqlScalar<T>(this IDbCommand dbCmd, string sql, Dictionary<string, object> dict)
440445
{
441-
if (dict != null) dbCmd.SetParameters(dict, true);
446+
if (dict != null) dbCmd.SetParameters(dict, excludeNulls: false);
442447
dbCmd.CommandText = sql;
443448

444449
using (var dbReader = dbCmd.ExecuteReader())
@@ -447,15 +452,15 @@ internal static T SqlScalar<T>(this IDbCommand dbCmd, string sql, Dictionary<str
447452

448453
internal static List<T> ByExampleWhere<T>(this IDbCommand dbCmd, object anonType)
449454
{
450-
dbCmd.SetFilters<T>(anonType, true);
455+
dbCmd.SetFilters<T>(anonType, excludeNulls: false);
451456

452457
using (var dbReader = dbCmd.ExecuteReader())
453458
return dbReader.ConvertToList<T>();
454459
}
455460

456461
internal static List<T> QueryByExample<T>(this IDbCommand dbCmd, string sql, object anonType = null)
457462
{
458-
if (anonType != null) dbCmd.SetParameters<T>(anonType, true);
463+
if (anonType != null) dbCmd.SetParameters<T>(anonType, excludeNulls: false);
459464
dbCmd.CommandText = OrmLiteConfig.DialectProvider.ToSelectStatement(typeof(T), sql);
460465

461466
using (var dbReader = dbCmd.ExecuteReader())
@@ -578,6 +583,9 @@ internal static List<T> GetFirstColumn<T>(this IDataReader reader)
578583
while (reader.Read())
579584
{
580585
var value = getValueFn(0);
586+
if (value == DBNull.Value)
587+
value = default(T);
588+
581589
columValues.Add((T)value);
582590
}
583591
return columValues;
@@ -612,6 +620,9 @@ internal static HashSet<T> GetFirstColumnDistinct<T>(this IDataReader reader)
612620
while (reader.Read())
613621
{
614622
var value = getValueFn(0);
623+
if (value == DBNull.Value)
624+
value = default(T);
625+
615626
columValues.Add((T)value);
616627
}
617628
return columValues;

tests/ServiceStack.OrmLite.Tests/SqlServerProviderTests.cs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,5 +183,77 @@ SELECT @Times AS Id
183183
Assert.That(result, Is.EqualTo(expected));
184184
}
185185

186+
[Test]
187+
public void Can_SqlScalar_StoredProc_passing_null_parameter()
188+
{
189+
const string sql = @"CREATE PROCEDURE dbo.DummyScalar
190+
@Times integer
191+
AS
192+
BEGIN
193+
SET NOCOUNT ON;
194+
195+
SELECT @Times AS Id
196+
END;";
197+
db.ExecuteSql("IF OBJECT_ID('DummyScalar') IS NOT NULL DROP PROC DummyScalar");
198+
db.ExecuteSql(sql);
199+
200+
var result = db.SqlScalar<int?>("EXEC DummyScalar @Times", new { Times = (int?)null });
201+
Assert.That(result, Is.Null);
202+
203+
result = db.SqlScalar<int?>("EXEC DummyScalar NULL");
204+
Assert.That(result, Is.Null);
205+
206+
result = db.SqlScalar<int?>("EXEC DummyScalar @Times", new Dictionary<string, object> { { "Times", null } });
207+
Assert.That(result, Is.Null);
208+
209+
result = db.SqlScalar<int?>("SELECT NULL");
210+
Assert.That(result, Is.Null);
211+
}
212+
213+
[Test]
214+
public void Can_SqlList_StoredProc_passing_null_parameter()
215+
{
216+
const string sql = @"CREATE PROCEDURE dbo.DummyProc
217+
@Name nvarchar(50)
218+
AS
219+
BEGIN
220+
SET NOCOUNT ON;
221+
222+
SELECT 1 AS Id, 'Name_1' AS Name WHERE @Name IS NULL
223+
UNION ALL
224+
SELECT 2 AS Id, 'Name_2' AS Name WHERE @Name IS NOT NULL
225+
UNION ALL
226+
SELECT 3 AS Id, 'Name_3' AS Name WHERE @Name IS NULL
227+
228+
END;";
229+
db.ExecuteSql("IF OBJECT_ID('DummyProc') IS NOT NULL DROP PROC DummyProc");
230+
db.ExecuteSql(sql);
231+
232+
var results = db.SqlList<DummyTable>("EXEC DummyProc @Name", new { Name = (string)null });
233+
Assert.That(results.Count, Is.EqualTo(2));
234+
Assert.That(results[0].Name, Is.EqualTo("Name_1"));
235+
Assert.That(results[1].Name, Is.EqualTo("Name_3"));
236+
}
237+
238+
[Test]
239+
public void Can_SqlList_StoredProc_receiving_only_first_column_and_null()
240+
{
241+
const string sql = @"CREATE PROCEDURE dbo.DummyScalar
242+
AS
243+
BEGIN
244+
SET NOCOUNT ON;
245+
246+
SELECT NULL AS Id, 'Name_1' AS Name
247+
UNION ALL
248+
SELECT NULL AS Id, 'Name_2' AS Name
249+
END;";
250+
db.ExecuteSql("IF OBJECT_ID('DummyScalar') IS NOT NULL DROP PROC DummyScalar");
251+
db.ExecuteSql(sql);
252+
253+
var results = db.SqlList<int?>("EXEC DummyScalar");
254+
Assert.That(results.Count, Is.EqualTo(2));
255+
Assert.That(results[0], Is.Null);
256+
Assert.That(results[1], Is.Null);
257+
}
186258
}
187259
}

0 commit comments

Comments
 (0)