Question

In my code bellow I use simple parameterized query.
It has a lot parameters and some can be NULL and some when null complain about FK.
How can I fix this to have optional parameters but without using stored procedure.
To be clear I want when parameter is null to avoid trying to update that field.

conn.Open();

                string sql = @"UPDATE UserProfile
                               SET FirstName = @p_FirstName
                                  ,LastName = @p_LastName
                                  ,Gender = @p_Gender
                                  ,DateOfBirth = @p_DateOfBirth
                                  ,CityId = @p_CityId
                                  ,MartialStatusId = @p_MartialStatusId
                                  ,ProfileImageId = @p_ProfileImageId
                             WHERE UserId = @p_UserId";

                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {                    
                    cmd.Parameters.AddWithValue("@p_FirstName", userProfile.FirstName);
                    cmd.Parameters.AddWithValue("@p_LastName", userProfile.LastName);
                    cmd.Parameters.AddWithValue("@p_Gender", userProfile.Gender);
                    cmd.Parameters.AddWithValue("@p_DateOfBirth", userProfile.DateOfBirth);
                    cmd.Parameters.AddWithValue("@p_CityId", userProfile.CityId);
                    cmd.Parameters.AddWithValue("@p_MartialStatusId", userProfile.MartialStatusId);
                    cmd.Parameters.AddWithValue("@p_ProfileImageId", userProfile.ProfileImageId);
                    cmd.Parameters.AddWithValue("@p_UserId", userProfile.UserId);

                    cmd.ExecuteNonQuery();

                }
Was it helpful?

Solution

You can construct your SQL so those optional parameters are never in it when they don't need to be:

var sql = new StringBuilder();
sql.Append(@"UPDATE UserProfile
               SET "); 

if(addFirstName) // <-- some boolean condition here
  sql.Append("FirstName = @p_FirstName, ");

// ... etc...

sql.Append(" WHERE UserId = @p_UserId");

Same with the actual parameters - don't add what you don't want to add.

OTHER TIPS

You can change your UPDATE statement as follows to avoid NULL-ing out the fields for parameters set to NULL:

UPDATE UserProfile
SET
    FirstName = CASE WHEN @p_FirstName_set THEN @p_FirstName ELSE FirstName END
,   LastName  = CASE WHEN @p_LastName_set  THEN @p_LastName  ELSE LastName END
--  ...and so on
WHERE UserId = @p_UserId

This doubles the number of parameters - for each optional parameter @XYZ you need to add a @XYZ_set parameter that you set to 1 if the @XYZ is used, or to 0 when the @XYZ is not used.

if (changeFirstName) {
    cmd.Parameters.AddWithValue("@p_FirstName", userProfile.FirstName);
    cmd.Parameters.AddWithValue("@p_FirstName_set", 1);
} else {
    cmd.Parameters.AddWithValue("@p_FirstName", "");
    cmd.Parameters.AddWithValue("@p_FirstName_set", 0);
}
// ... and so on

You can add a function to encapsulate this if statement.

This approach lets you set values to NULL if you need to do so, because the information on whether the corresponding parameter is set or not is no longer contained in the value of the parameter itself.

Note that the query remains static regardless of how many fields are set, so your RDBMS could avoid building a new query plan each time you set a different group of parameters.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top