CosmosDb+System.Text.Json - I take it all back
Knowing how to find answers from the incredibly useful, informal documentation that make up the collective knowledge on a subject turns out to be key. Also, paying attention helps.
When you don't it sometimes results in an well deserved face palming moment when you say, "Why didn't I find/think/know/deduce that before I shot off my big mouth?"
And that's the case when you (in this case, me) write a snarky post about how something doesn't work when maybe if you'd had better access to the collective knowledge base, you'd have saved days of work and not a little embarrassment. But then you'd be the Borg. Or is it a Borg? I don't know... maybe both.
The solution came in the form of a comment in a GitHub repository where someone shared how they'd fixed the problem. They used an option that I didn't even know existed on a method call. And that's on me because I supplied every other possible parameter to that method except that one when I wrote my generic repository.
If you haven't read this post, don't. It doesn't exist, and I don't know what you're talking about.
If you did, forget I said all that and use the steps below to get CosmosDb and System.Text.Json
working together without compromising. And bonus - future proofing your app when System.Text.Json
finally becomes the default serializer for CosmosDb.
Get a custom serializer.
You'll need a custom serializer to use instead of the Newtonsoft.Json
one that's built in. You can download that custom serializer here. It's from the Microsoft.Azure.Cosmos.Samples
repository so you can trust it.
Change your CosmosClient initialization code.
As you can see, I'm setting PropertyNamingPolicy = JsonNamingPolicy.CamelCase
so that my property names inside the document are all CamelCase. If you're new to CosmosDb, remember that there is a case sensitive, required property with a name of id
on every document.
Using a JsonNamingPolicy
of CamelCase
means I don't have to put [JsonPropertyName("id")]
on my Id
property or other Json attributes sprinkled around in my code.
What's important here is that this change does not affect the casing on LINQ
queries. So, if you stop reading here, you'll be unhappy.
Fix your LINQ queries.
If you're using LINQ
for CosmosDb you might be writing something like this:
Unfortunately, now that you're no longer using the default serializer, that LINQ
statement generates the SQL
below which has the wrong casing and yields the wrong result.
But you can fix that by changing your original query to this:
Now, the SQL
generated looks like this:
As it turns out, for me anyway, I wrote a generic repository for my CosmosDb needs and I only needed to make the change in a single spot and voila, everything works as advertised.
Thanks to the people from Microsoft for responding in under 24 hours to a Tweet about this problem I was having and even more thanks for already solving it. And a special thanks to the people at DevBetter for getting this out in the wind.