Oleksandr
Oleksandr

Reputation: 131

Ignore null values when saving data in CosmosDb with Entity Framework

I use CosmosDb with the Entity Framework. I need that when saving data if one of the properties is null, it is stored as undefined. Is there any option to initialize DbContext from CosmosClient, or set CosmosSerializationOptions?

I tried the following option, but it does not work for me:

context.Database.GetCosmosClient().ClientOptions.SerializerOptions = new CosmosSerializationOptions()
{
     IgnoreNullValues = true
};

The option without using EF is working:

CosmosClient cosmosClient = new CosmosClientBuilder(EndpointUri, PrimaryKey)
   .WithSerializerOptions(new CosmosSerializationOptions() { IgnoreNullValues = true })
   .Build();
//The current result
{
    "Id": "fad8b443-6d10-4009-853c-efb6aac18031",
    "Discriminator": "User",
    "FirstName": "Charley",
    "LastName": null
}
//Expected result
{
    "Id": "fad8b443-6d10-4009-853c-efb6aac18031",
    "Discriminator": "User",
    "FirstName": "Charley"
}

Upvotes: 3

Views: 3728

Answers (2)

MikeRoz
MikeRoz

Reputation: 61

I'm not using Entity Framework in my code, but in searching for the right way to get Cosmos to ignore null values, I found an alternative solution that may work for you.

I was inspired by the answer to this question to add a JsonProperty attribute with ItemNullValueHandling set to NullValueHandling.Ignore for the classes I'm saving, like so:

[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Foo
{
    [JsonProperty(PropertyName="id")]
    public string Id {get; set;}

    [JsonProperty(PropertyName = "bar")]
    public string Bar { get; set; }

    [JsonProperty(PropertyName = "baz")]
    public string Baz { get; set; }
}

async void Main()
{
    Foo f = new Foo() { Id = "1", Bar = "bar" };
    string azureSqlCoreApiPrimaryKey = "[REDACTED]";
    string azureSqlCoreApiUrl = "[REDACTED]";
    string cosmosDbName = "[REDACTED]";
    string cosmosContainerName = "test";
    CosmosClient cosmosClient = new CosmosClient(azureSqlCoreApiUrl, azureSqlCoreApiPrimaryKey);
    var cosmosDb = cosmosClient.GetDatabase(cosmosDbName);
    var cosmosContainer = cosmosDb.GetContainer(cosmosContainerName);
    
    await cosmosContainer.CreateItemAsync(f);
}

In my tests, the document would have a null 'baz' attribute if and only if I commented out the JsonObject property.

The accepted answer to that question suggests that you modify the options on a JsonSerializer object instead of touching each class you're trying to save. This is analogous to how you tried to modify the serialization options on your CosmosClient, but were ultimately unable to do so. I ended up moving to modifying the CosmosClient serialization options myself, as you demonstrated. But in a case where you can't modify the serialization options, but you can modify the class you're writing, this is a possible workaround.

Upvotes: 5

Tiny Wang
Tiny Wang

Reputation: 15991

I've tried the sample and I found it really has no option to set IgnoreNullValues when initialize the client, and here's the description:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder.UseCosmos(
                "https://xxx.documents.azure.com:443/",
                "primary key",
                databaseName: "Tasks",
                options => {
                    options.SerializerOptions(....);//there's no property choice to set
                });

enter image description here

According to this situation, what you can do is modify the entity, such as removing the null property, and I found a similar question in st, I think you can refer to it. And if your entity always exists null value in some specific property(e.g one property 'userConf' may be a null property, you can create another entity without this property), you can even create another entity to meet your requirement.

Upvotes: 1

Related Questions