4

I'm noticing a trend towards using a dictionary of string to object (or sometimes string to string), instead of strongly typed objects. For example, the new Katana project makes heavy use of IDictionary<string,object>. This approach avoids the need to continually update your entity classes/DTOs and the database tables that persist them with new properties. It also avoids the need to create new derived entity types to support new types of entity, since the Dictionary is flexible enough to store any arbitrary properties.

Here's a contrived example:

class StorageDevice { 
    public int Id { get; set; } 
    public string Name { get; set; }
}

class NetworkShare : StorageDevice {
    public string Path { get; set; }
    public string LoginName { get; set; }
    public string Password { get; set; }
}

class CloudStorage : StorageDevice {
    public string ServerUri { get; set }
    public string ContainerName { get; set; }
    public int PortNumber { get; set; }
    public Guid ApiKey { get; set; }
}

versus:

class StorageDevice {         
    public IDictionary<string, object> Properties { get; set; }
} 

Basically I'm on the lookout for any talks, books or articles on this approach, so I can pick up on any best practices / difficulties to avoid. Here's my main questions:

  • Does this approach have a name? (only thing I've heard used so far is "self-describing objects")
  • What are the best practices for persisting these dictionaries into a relational database? Especially the challenges of deserializing them successfully with strongly typed languages like C#.
  • Does it change anything if some of the objects in the dictionary are themselves lists of strongly typed entities?
  • Should a second dictionary be used if you want to temporarily store objects that are not to be persisted/serialized across a network, or should you use some kind of namespacing on the keys to indicate this?
5
  • 3
    I'd call this approach "Horrible", frankly. Strings are a terrible key for data, they're easily typoable and any issues with them are only thrown up at runtime. If for some reason you cannot use properties, I see no downside to having a dictionary of SomeEnum -> Object, which still sucks due to losing type safety on one end, but gains a very little back on the other.
    – Phoshi
    Commented Nov 7, 2013 at 14:19
  • @Phoshi yes, this is essentially taking a dynamic language approach and applying it to a statically typed language, so you sacrifice static typing for extensibility.
    – Mark Heath
    Commented Nov 7, 2013 at 15:01
  • 1
    Except that there are better ways to achieve this sort of flexibility that don't end up killing type safety quite so bad, and I'm not sure what benefit you're getting here other than it being quicker to develop that component. Now, if there aren't many other components, that's totally valid, but losing type safety in your data storage engine is insane in a larger project. At best, you're going to litter your code with instanceof and (Casting).
    – Phoshi
    Commented Nov 7, 2013 at 15:50
  • No, it's instanceof that this approach eliminates since there are no derived types any more. I didn't want to bloat the question with long details about why I'm interested in this approach, but a big part of the driver is getting rid of instanceof, and dealing with the challenges of needing to deserialize objects from any previous (or future) version of the application.
    – Mark Heath
    Commented Nov 7, 2013 at 15:58
  • If you're never doing runtime typechecks then you can only sanely treat everything as "object". I mean, I guess you can treat everything as strings if you ToString everything before use, but this is still all of the disadvantages of loosely typed programming without the metadata that actually makes that work. Treating everything as Object and never changing types isn't making the type system more flexible, it's making the type system work against you for no benefit.
    – Phoshi
    Commented Nov 8, 2013 at 9:24

3 Answers 3

1

If you're taking this approach, why stick with a traditional relational database? NoSQL databases like MongoDB let you apply "fuzzy schemas" to data which should allow different versions of the software to pick out documents that it expects and leave out the others (or fill it with nulls)

2
  • yes, essentially I want the benefits of schemaless objects that you get with nosql, but I'm stuck in relational database world because the application in question is already installed on thousands of sites worldwide. Changing database would be virtually impossible at this stage, so I'm considering this as a kind of poor man's NoSQL, possibly using JSON to serialise the objects.
    – Mark Heath
    Commented Nov 9, 2013 at 9:50
  • 1
    Ah, so you're stuck with the database already. Are you using SQL Server? I don't know how this feature works, performance-wise, but there's an XML datatype in SS2005+ that lets you do [XPath queries](technet.microsoft.com/en-us/library/…. You might be able to use this to build what you're looking for.
    – nemec
    Commented Nov 9, 2013 at 21:15
1

You should probably make this decision based on your actual data model. If it is relatively static then I think you would be better taking the hit of changing your schema and updating your classes and DTO's. It may sound like a lot of work but if you are C# and Sql land you will probably end up with a better solution in the long run.

You may also want to consider a hybrid approach where most of your properties are strongly typed but also have a dictionary for more dynamic or sparse properties.

Ideally to get a nice solution for your situation you'd either switch to a dynamic language or schemaless database or both.

0

MY approach (presently) is JSON.NET for (De)Serializing ...for more on that see https://stackoverflow.com/questions/20711986/entity-framework-code-first-cant-store-liststring/37207034#37207034

.. & Linq to JSON for querying the JSON if you find the need to do that.

JSON.NET seems quite performant and reliable for serializing a whole lot of Dictionary<string, object> things into SQLite text columns in my use-case. My use-case is <string,string> at its lowest level.

Using Dictionaries with class indexers gives you a pseudo schema-less property-style of addressing things ... Class["key"].Object.Property. If you store the Object properties as a Dictionary<string,string> and embed that Dictionary into a new class as a property then you end up with a Syntax like Class["key"]["Object"].Value. The other advantage of using the indexer is you can code towards guarding against the usual run of Exceptions, nulls, hits-and-misses etc. you get with Dictionaries. They are still Dictionaries so you can enumerate over them and all those sorts of things as well.

Not the answer you're looking for? Browse other questions tagged or ask your own question.