There was an interesting discussion on the LINQ Project General forum today (scroll down toward the end where we start talking about what the EF can and cannot do), and there were a couple of key points I wanted to capture since we’ve had so many discussions about persistence ignorance. Two things which are requested fairly often when folks start to get serious about the object model they expose with their entities are:
- Making the default constructor private / forcing consumers to use factory methods.
- Creating read-only properties.
Neither of these happens by default with the code generated from the EF designer or from edmgen, but both are possible (even fairly straightforward) to do with the EF, so I want to make sure folks know about this.
Getting rid of the public parameterless constructor
First off, it’s important to realize that the EF does require that there be a parameterless constructor for each entity type (as described in this previous post). This constructor is used by the system when materializing the results of queries. This constructor does not, however, have to be public. So if you want other consumers of your object model (such as an app developer–not the EF itself) to always use a constructor which takes a set of required parameters or to use a factory method, then you can just declare a private parameterless constructor in your partial class (or your own class directly if you are using IPOCO rather than the generated code). This constructor can have business logic for initializing your entity if necessary, and it will be called when materializing objects from the database. Consumers of your class will have to call some other public constructor or factory method you supply.
Another request which has been made, by the way, is that the mapping should make it possible to specify a constructor with parameters or a factory method which even the EF will use instead of the parameterless constructor. This is something we will consider for future releases, but it won’t be a part of the first release of the EF.
Creating read-only properties
This one is a bit harder because there’s no straightforward way to do it with the automatically generated code. If you are writing your own class, though, it’s simple. Just make the property which the EF persists private and then create a new public property with only a getter. Unfortunately the EF will not allow you to attribute a field directly–it must be a property, and that property must (in the first version of the EF) have the exact same name as the corresponding property in your conceptual model, but there’s nothing in the system which forces you to make that property public.
So, if you want to try this out real quick, you can just take the output of codegen and change the property from public to private and then add a new property to your partial class which is public and has only a getter which access the private property (or the field directly). The EF will use the getter and setter of the property which matches the conceptual model when materializing query results or reading data to write back to the database, but the consumers of your object model will only have access to your public property which can be read-only and/or have various additional business logic in it.
NOTE: I do not normally recommend editting the output of the code generator because if you ever need to regenerate your code these changes will be lost. This is just a quick way to try out this capability of the EF. If you need to make your persisted properties private, then you will need to switch to maintaining your own data classes either by taking a one-time snapshot of the output of codegen and then manually modifying the class from there on or outright writing your own IPOCO classes.