14

I've got a scenario where a string in C# can be null. I need it to be NULL on SQLServer.

I'm sending it to SQLServer using Dapper with a query like:

connection.Query<MyObject>("[dbo].[sp_MyStoredProcedure]"), new
{
    StartDate: startDate
}, commandType: CommandType.StoredProcedure);

Where startDate is the string that can sometimes be equal to null.

The stored procedure's parameter is

@StartDate varchar(10) = NULL

When it's is NULL it returns all records. I've confirmed this behavior works via SSMS.

I read this post by Marc Gravell that states:

The null vs DBNull issue is a constant cause of confusion; however, generally if people say null in C# they intend null in SQL. This is the approach that dapper adopts.

This leads me to believe that when the string is set to null, it should send DBNull.Value to SQLServer.

However, this doesn't appear to be the case. I get back 0 records from SQLServer when sending a null string. This seems indicative of sending an empty string, rather than a DBNull.Value.

Also, I can't send DBNull.Value directly:

connection.Query<MyObject>("[dbo].[sp_MyStoredProcedure]"), new
{
    StartDate: DBNull.Value
}, commandType: CommandType.StoredProcedure);

This produces an exception within Dapper:

The member StartDate of type System.DBNull cannot be used as a parameter value

Question

How can I send NULL to SQLServer, using Dapper, when I have a string in C# that can be null?


Important

Dapper does indeed send NULL when a string is null. This assumption was a mistake on my part based on faulty information. Nonetheless, this question may serve to help someone else who makes an equally faulty assumption.

Furthermore, the accepted answer provides a good mechanism for dealing with optional or conditional parameters.

Community
  • 1
  • 1
crush
  • 16,713
  • 9
  • 59
  • 100
  • +1. It seems to me the question is quite valid for SO. – Miller Feb 07 '14 at 15:20
  • 3
    +1. Don't worry about the downvote, I guess somebody is having a bad Friday. – Habib Feb 07 '14 at 15:22
  • @crush, the links says `So I have to change my code to: if (contact.IsActive.HasValue) p.Add("@isActive",contact.IsActive.Value); So I have to change my code to: if (contact.IsActive.HasValue) p.Add("@isActive",contact.IsActive.Value); So that it only adds the parameter if it has a value.` so you have to add only when it has value – Miller Feb 07 '14 at 15:25
  • I need to delete this question. I made an incorrect assumption based on faulty information provided to me by the dba who created the stored procedure. /sigh In fact, Dapper is sending `NULL`. It's the stored procedure's logic that is flawed. Sad that I can't rely on the dba, and had to wade through it myself to find the flaw. – crush Feb 07 '14 at 15:29
  • Maybe I will leave the question in case someone else makes a faulty assumption like me. – crush Feb 07 '14 at 15:32
  • 1
    @crush, this is a good question and I would ask you to leave it instead of deleting it, **This could be helpful for future visitors.** You can add your own answer indicating the mistake. – Habib Feb 07 '14 at 15:32
  • I'll edit the question to include a disclaimer about the mistake, and accept the quality answer below. – crush Feb 07 '14 at 15:33
  • First of all, you cannot use `.ToString()` on a null. It's something I learned the hard way, as it concatenated my db and lists before.. Interesting. I would simply sanitize it before putting into a db. From what I understand, you want to read the `null` object and set it in the db as a `"NULL"` string? – theGreenCabbage Feb 07 '14 at 15:48

2 Answers2

13

Yes, dapper knows to replace reference-null with DBNull.Value whenever it sees it. Because DBNull is my arch -nemesis, and if I never see it again in my application code (library code is different) I will die a little happier.

See also: https://stackoverflow.com/a/9632050/23354

Community
  • 1
  • 1
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 2
    Couldn't agree more, that's a great answer. Found it earlier. Thanks for the great work on Dapper. It's a godsend – crush Feb 07 '14 at 22:31
5

You can choose not to send StartDate.

Example:

dynamic parameters = new {

};

if (!string.IsNullOrWhiteSpace(startDate)) 
{
   parameters.StartDate = startDate;
}

connection.Query<MyObject>("[dbo].[sp_MyStoredProcedure]"), parameters, commandType: CommandType.StoredProcedure);

Edit:

Also, your stored procedure must accept nulls. Here's an example:

CREATE PROCEDURE [ExampleProc]
   @StartDate datetime = null
AS
   Select @StartDate
Ed Guiness
  • 34,602
  • 16
  • 110
  • 145
Scen
  • 1,700
  • 13
  • 15
  • 1
    This is a good answer, but my question is based on incorrect information. **Dapper does send `NULL` when `string` is null.** Nonetheless, this is a good approach to my problem, and I will probably use this anyways. Thanks for this answer! – crush Feb 07 '14 at 15:30