Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option SqlMapper.Settings.ApplyNullValues is not respected #2086

Open
HugoRoss opened this issue May 20, 2024 · 0 comments
Open

Option SqlMapper.Settings.ApplyNullValues is not respected #2086

HugoRoss opened this issue May 20, 2024 · 0 comments

Comments

@HugoRoss
Copy link

HugoRoss commented May 20, 2024

In the following case, option SqlMapper.Settings.ApplyNullValues is not respected, null-values are not assigned:

I have a DTO (PersonDto) with some properties (Id, GivenName, MiddleName, Surname, Picture). The Id is of data type Int32, the other properties are Settable<T>:

public class PersonDto {

    public int Id { get; set; }

    public Settable<string> GivenName { get; set; }

    public Settable<string?> MiddleName { get; set; }

    public Settable<string> Surname { get; set; }

    public Settable<byte[]?> Picture { get; set; }

}

Settable<T> is a structure (value type) that allows to distinguish whether a value was assigned null or was not initialized. Imagine now a data access method that returns a list of PersonDto and that has a Boolean parameter IncludePicture that is false by default and that adjusts the SQL query accordingly to avoid loading expensive property Picture when it is not needed. When the consumer of this method now accidentally accesses uninitialized property Picture, an InvalidOperationException is thrown. Unfortunately that is now also the case for the MiddleName that should have been initialized with null and wasn't. Here the test method:

[TestMethod]
public void Null_Value_Is_Not_Applied_Although_ApplyNullValues_Flag_Is_Set() {
    LocalDB localDB = LocalDBManager.CreateLocalDB("SQL-Scripts"); //Creates a new database on LocalDB-SQLServer 

    IDbConnection dbConnection = localDB.DatabaseConnection;
    dbConnection.EnsureSettableConvertersLoaded(); //Sets ApplyNullValues and registers the converters to Settable<T>
    Assert.IsTrue(SqlMapper.Settings.ApplyNullValues);
    PersonDto actual = dbConnection.QuerySingle<PersonDto>("SELECT Id, GivenName, MiddleName, Surname FROM Person WHERE Id = 3;");
    Assert.IsTrue(SqlMapper.Settings.ApplyNullValues);
    Assert.AreEqual("Kerry", actual.GivenName);
    Assert.AreEqual("Norton", actual.Surname);
    Assert.IsNull(actual.MiddleName.Value); // <--- Fails (null was not assigned!)
    Assert.ThrowsException<InvalidOperationException>(() => actual.Picture.Value); //Works as expected, throws an exception because the value was not initialized.
}

And here the prove that the bug is not in Settable<T>:

[TestMethod]
public void Settable_Works_As_Expected() {
    PersonDto actual = new PersonDto();
    actual.GivenName = "Kerry";
    actual.MiddleName = null;
    actual.Surname = "Norton";

    Assert.AreEqual("Kerry", actual.GivenName);
    Assert.AreEqual("Norton", actual.Surname);
    Assert.IsNull(actual.MiddleName.Value); //Works, null was assigned.
    Assert.ThrowsException<InvalidOperationException>(() => actual.Picture.Value); //Works as expected, throws an exception because the value was not initialized.
}

Here the complete test project (Visual Studio 2022 solution) including database initialization on test execution (using LocalDB):
BugReport.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant