Design Meeting Notes - December 13, 2012
ToTable and complex types
Complex types can be explicitly configured as a complex type either by attribute or using the fluent API. If this is not done, then a type is determined to be a complex type by convention based on a number of criteria. One of these is that any type mapped
to a table will not be considered a complex type by convention. This means that a custom convention that calls ToTable on a type can cause that type to become an entity type when without the convention it would have been a complex type. It is quite easy to
do this by mistake.
- Leave behavior as is
- Make ToTable called from a convention become just a hint, and if it is the only thing preventing a type being a complex type, then ignore the ToTable and make the type complex
- Change the conventions behavior to not visit complex types
We decided to leave the behavior as is because:
- It’s legitimate to use ToTable to map a type to a table and have it not be a complex type
- It’s very easy to explicitly configure a type as a complex type—we believe this is much more comment than by-convention complex types anyway
- Making ToTable a hint adds extra complexity and concepts that will in general make conventions harder to understand
- Visiting complex types is required for many other important scenarios, such as common property configurations
Filtering enum properties
Should it be possible to configure all enums, or all int enums etc., through use of enum base class. Decision: doesn’t seem worthwhile; YAGNI.
Unique Identifier primary keys and clustered/non-clustered
Currently Migrations creates clustered GUID primary key columns; this is not necessarily the ideal behavior. Full details can be found in the
comments to this bug, but the conclusions are:
- For store-generated GUID primary keys, Migrations should by default:
- Use NewSequentialId
- Use a clustered index
- For client-generated GUID primary keys, Migrations should by default:
- Use a non-clustered index
We will also add support to Code First to allow the default for clustering to be overridden. Not all databases will support this, in which case they can ignore the configuration.
Specifically, we will:
- Add "clustered" parameter (default true) to PrimaryKey, AddPrimaryKey APIs
- Add "clustered" parameter (default false) to Index, CreateIndex APIs
- Update Migrations scaffolding to set clustered = false for client-generated GUID primary keys
- Update Migrations to use NewSequentialId for store-generated GUID primary keys
Potential contribution for pluralization service
A discussion was started about a
potential contribution for making the EF pluralization service public. There are several dimensions to this discussion:
- The name of the service (Pluralization or Inflector)
- The mechanism by which a pluralization service is selected by EF and which classes/APIs should be made public
- Potential use of the service by the designer
The suggestion was made to change the name to Inflector, which is a more common name for similar services in other frameworks. The general consensus was that the current name is clearer given that:
- Tooling and documentation already uses the term pluralization
- Even if we update current tooling and documentation it still means that historical discussions, questions on the forums, etc. will have the term pluralization
- Currently the service only performs pluralization, not other forms of inflection
Service resolution and API
A couple of important points:
- Changing the behavior of the current code in any locale would be a breaking change and the feeling was that we would not take such a breaking change. This means that some form of configuration/registration will be required to use a different service.
- Currently, the only place in the EF runtime where the pluralization service is used is in Code First conventions; specifically, the PluralizingTableNameConvention and PluralizingEntitySetNameConvention.
Let’s assume for a moment that the EF Service Locator is used for registration of and obtaining a pluralization service. Should the registration be:
- One per app-domain? That is, any time EF uses pluralization it will always use the same service.
- One per context type? That is, different pluralization can be used for different contexts. But what if the model builder is being used without a context?
- Registered/obtained per locale? But what if my application is running in some locale, but the database was created in a different language?
- Other possibilities and combinations are also possible.
There doesn’t seem to be a clear correct answer to the questions above. We could certainly create something quite complicated, but it’s not clear that the complexity would ever really be needed.
So maybe we should take a slightly different approach based on the fact that conventions are the only thing that use the service. With public conventions it is now possible to create conventions that perform whatever pluralization (or other inflection) is
needed. Given this, the preferred approach agreed upon by the people in the meeting is:
- Make the pluralization service classes public such that external implementations are possible
- There probably needs to be some refactoring/reorganization of this code
- The pseudo service registration mechanism that only returns an English pluralizer (i.e. the CreateService method ) should be removed
- Refactor PluralizingTableNameConvention and PluralizingEntitySetNameConvention such that they can be constructed with any implementation of PluralizationService
- Don’t provide any mechanism to register/resolve pluralization services at this time
- Allows external pluralization services to be implemented
- Allows any pluralization service to be used by Code First simply be adding an appropriate instance of the PluralizingTableNameConvention
- Allows pluralization to be used by Code First in other places by implementing other conventions
- Doesn’t preclude adding registration and lookup for pluralization services in the future if it becomes clearer how this will be used
Pluralization by the designer
Discussions of how external services might be used by the designer revealed that again it is not clear how the designer would discover which service to use. It seemed most likely that the designer would not use the runtime Service Locator because the service
would be needed before the user has written/configured any runtime code. There could be a different mechanism for registering pluralizers for the designer, or it could possibly scan referenced assemblies and let the user pick any that was found. The approach
described above does not seem to preclude designer use by either of these mechanisms.