Nullable=”False”… but when exactly?

If you look at the EDM and in particular the metadata it considers important, one thing is clear: Persistence is the Priority.

For example this:

<Property Name=”Firstname” Type=”String” Nullable=”False”/>

Tells us that the Firstname property can’t be null when persisted.

If however the EDM Type System is used to describe the signature of a function, the Nullable constraint may or may not apply.

You may be able to call the function with an Entity with its’ Firstname property set to NULL, or … maybe not.

Essentially we can’t know whether the Nullable facet (i.e. a persistence constraint) applies in this context.

This distinction makes me think of the contract feature which is coming in .NET 4.0. In that in both situations we are really looking for more validation.

It also makes me wonder whether, in hindsight, it might have been better to have something like this instead:

<Property Name=”Firstname” Type=”String” ssdl:Nullable=”False”/>

Here the ssdl namespace qualifies the nullable constraint. The ssdl is simply shorthand for the storage model or context. The natural implication is that in order to persist the Entity to storage, the Firstname can’t be null. Which in turn further implies, a guarantee, that when materializing entities from storage, the Firstname will never be null.

I wonder if when we look at evolving and growing the EDM, we should be thinking about other contexts too.

Now we’ve taken the first step to supporting other contexts with Annotations, but I wonder if that is enough.

This idea of context seems more fundamental to me.

Its not necessarily (as I think we all thought) just about adding addition information / constraints / whatever, it may also involve, re-defining the same information for a different context.

What do you think?

Comments (5)

  1. bittercoder says:

    I’m trying to think of what kinds of context you think would make sense to model declaratively… argument level constraints and entity/property level constraints make sense… perhaps some basic validation that’s enforced only upon initial create, or only upon an entity being updated (i.e. a modified date property, that’s only non-nullable upon update, and must be null on create).  

    But I get the feeling your envisaging something more all-encompassing, would you see key parts of the model maybe even changing the shape of the entity entirely depending on context… and what would those contexts be??

  2. bittercoder says:

    Also I think invariant constraints should be explicit as to which contexts they apply to – so I like the idea of scoping Nullable="True" to storage 🙂

    One problem I could see is when too many contexts exist you may end up having to restate the same constraints (concepts) across them all (i.e. failing at DRY) – for example perhaps by default a storage length constraint on a string property is only checked upon persistence, but you wanted to have a contract enforced by the property itself so a user could never assign a string of incorrect length to the property even if the entity was transient – obviously a hokey example, but you probably get my drift.

    In that case you’d almost want the reverse, where the constraint itself could be defined once and include which contexts it applies to… but that almost leads on to a constraint language / constraint DSL being required.

    Which remind’s me of things I’ve done in the past (and disliked) using OCL in UML models… hmm…

  3. Alex D James says:

    Well I’m definitely not sure. I just have an instinct telling me there is something in this.

    Although your warning about constraint DSL, doesn’t go unheeded.

    I wonder though, perhaps some sort of Constraint DSL is the natural next step for the EDM? Not sure, but I’m definitely thinking…

  4. Alex D James says:

    PS one option to avoid failing DRY is the use of a core model (akin to the convention) with perspectives (akin to configuration) that tweak the model.

    What do you think?


  5. bittercoder says:

    Perhaps you just need some value format that allows either constant values and/or a simple expression ah la "{self=>ssdl:MaxLength-2}" – I’m not sure I’m too concerned about repetition i.e. multiple attributes that state the same thing in different contexts, so much as the opportunity for duplication/errors creeping in if you’re having to restate a constant.

    As for a constraints DSL – I’m wondering where the extents of a constraints scope would be, and how validation fits into that story… I would imagine constraints would be more of a repository level concern i.e. encompassing at most a single aggregate root…  which still leaves metadata about services performing validation across multiple aggregate roots (which may have external dependencies etc.) out in the cold.

    Also to play devils advocate – isn’t the aim of metadata to be easily consumed, a DSL by it’s very nature seems like something that’s not all that friendly to the conventional set of tools people will be using to consume the rest of the metadata (just like Expression<Func<…>> isn’t all that easy for most developers to work with).