question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

EntityPropertyConverter::ConvertBack<T> intolerant to properties in dictionary not found as properties on T

See original GitHub issue

The EntityPropertyConverter::ConvertBack<T> method is currently extremely fragile in terms of being able to deserialize a set of properties that does not exactly match the shape of the T being specified. Consider the sample repro program below where I have a class Test with some properties Id and Nested. If my properties dictionary contains a key other than those exact property names (i.e. SomePropIDontHave), then the call to convert back will throw a completely nondescript NullReferenceException. The NullReferenceException is due to this code that just blindly expects to find the property on the T and use it:

https://github.com/Azure/azure-storage-net/blob/bdeb107c5fc1ad6db84fe6deaff17b15717aac0c/Lib/Common/Table/EntityPropertyConverter.cs#L360-L365

My initial expectation would be that, at the very least, a more specific exception would be thrown that tells me exactly which property couldn’t be deserialized rather than a NullReferenceException. For example, given the code above, adding something like this:

if (propertyToGet == null)
{
    throw new MissingPropertyException($"No property was found on type {parentProperty.GetType().FullName} that corresponds to {propertyPath}.");
}

My desire for this API though would be giving me a little more control by allowing me to tell it to “relax” and just deserialize what it can. Since ConvertBack already takes an EntityPropertyConvertOptions parameter in one of its overloads, this could be added to that options class in the form of a bool IgnoreMissingProperties property that basically tells it: hey, if you can’t find a property on my T that matches the key coming out of the dictionary, just go ahead and ignore it. That might then look something like this:

if (propertyToGet == null)
{
    if (entityPropertyConverterOptions.IgnoreMissingProperties)
    {
        continue;
    }

    throw new MissingPropertyException($"No property was found on type {parentProperty.GetType().FullName} that corresponds to {propertyPath}.");
}

Sample Repro Code

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using System;
using System.Collections.Generic;

namespace EntityPropertyConverterTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var rawProperties = new Dictionary<string, EntityProperty>
            {
                ["SomePropIDontHave"] = EntityProperty.GeneratePropertyForString("Hmmm"),
                ["Id"] = EntityProperty.GeneratePropertyForString("MyId123"),
                ["Nested_NestedId"] = EntityProperty.GeneratePropertyForString("MyNestedId456"),
            };

            // NOTE: this will throw a NullReferenceException unless you comment out the SomePropIDontHave entry in the dictionary initializer above
            var test = TableEntity.ConvertBack<Test>(rawProperties, new OperationContext());

            Console.WriteLine($"Id: {test.Id}");
            Console.WriteLine($"NestedId: {test.Nested?.NestedId}");
            Console.ReadKey();
        }

        public class Test
        {
            public string Id { get; set; }
            public TestNested Nested { get; set; }
        }

        public class TestNested
        {
            public string NestedId { get; set; }
        }
    }
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
lukoscommented, Jul 12, 2018

@erezvani1529 can you explain what you mean? Since CosmosDB Table API is not a replacement for Azure Table Storage, why would development be frozen on new features?

@doguva-msft Is there anywhere else to get this fix? It is a problem for me since your code is great for not inheriting from ITableEntity but I cannot put a BsonId in my model and therefore EntityPropertyConverter crashes when it tries to deserialize it.

3reactions
doguva-msftcommented, Apr 14, 2018

Hi, I am not from the azure team but I wrote the EntityPropertyConverter class. Your suggestion of leveraging EntityPropertyConverterOptions is right on target. The main reason I added that options class is to allow customizations in the api without changing any method signature and giving more control on the callers for the behaviour. Your proposed solution above looks good. Minor comments you may want to save parentProperty.GetType() to a variable not to call it second time for logging and in the log statement you may also want to log the specific property (properties[i]) that does not exist in T.

If azure team is happy to take this in you should submit a Pull request with your proposal.

Thanks Dogu

Read more comments on GitHub >

github_iconTop Results From Across the Web

Properties of extended dictionary won't show in serialization
I find it simpler to (de)serialize to a DTO rather than to work directly with Utf8JsonReader and Utf8JsonWriter as edge cases and naming ......
Read more >
Why isn't getproperty defined for Dictionaries?
Not all keys can be properties. For example Dict(1=>2) is fine, but x. 1 is not.
Read more >
Dictionary<TKey,TValue>.Item[TKey] Property
The property is retrieved and key does not exist in the collection. ... values if a program often must try key values that...
Read more >
Excel VBA Dictionary - A Complete Guide
This post contains everything you need to know about using the VBA Dictionary. There are tons of code examples including a real world...
Read more >
Is there a better way to use C# dictionaries than ...
Use the TryGetValue method if your code frequently attempts to access keys that are not in the dictionary. Using this method is more...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found