If you’ve read the post on the new types available in the System.Data.Services.Providers namespace, you might have jumped in and tried to write your own metadata provider for some not-quite-there interesting data model. Not for the faint of heart, but certainly an exercise that will increase your understanding of how WCF Data Services views the world.
If you’ve already gone ahead and written some code, you’ve probably run into one of these two error messages:
Resource Type ‘namespace.name‘ returned by the provider is not read-only. Please make sure all the types are set to read-only.
Entity Set ‘name‘ returned by the provider is not read-only. Please make sure all the sets returned by the provider are set to read only.
The way to make these go away is pretty straightforward: call the SetReadOnly method on the instance you’re returning from your provider. I want to take a minute though to explain the rationale behind the design.
If you remember an old post of mine from a long time ago, you’ll see this pattern looks a lot like the Freezable pattern in WPF, where an object is mutable until an explicit API method call is made to make it read-only. This allows you to build the instance incrementally and then, when you expose it to a more complex system that won’t support the object changing, make it read-only.
We could have just made the type take all the required initialization arguments in the constructor, and then there would be no need to do this extra step. One problem with this is that having to get all the information up-front is a bit cumbersome, especially when you have types like ResourceType that have a collection of properties.
A more important problem that has a broader principle underlying it is this: resouce types can refer to each other through their properties, and thus it’s just not possible to initialize them simultaneously without changing at least one of them after creation. Otherwise, the first instance that is created won’t be able to reference the second one.
If we were only considering hierarchies of types, you could image we might make do, although it’s again cumbersome to use the API, as you have to figure the right order (first the parents, then the children that refer to them). In our case it doesn’t even matter – there are ciruclar references when a type A refers to B and B refers back to A, so there is really no way around it.
Next week, some ideas on other possible designs for this sort of situation.