Design Meeting Notes - April 11, 2013
Recent changes allow provider services to be grouped together by having DbProviderServices implement IDbDependencyResolver. See the
EF6 provider model documentation for more details. Most provider-related services are keyed using the provider invariant name. This means that when multiple DbProviderServices implementations are registered they can each resolve additional services as appropriate
independently of each other. However, there are currently two services that are not always keyed by provider invariant name because the provider cannot be known at the time the service is requested. These are:
- IDbConnectionFactory for the default connection factory
- DbSpatialServices for the global spatial provider
For these services the DbProviderServices closest to the top of the chain will get a chance to resolve first. This topmost provider can be considered the “default provider” since, everything else being equal, it gets the chance to resolve services first.
The default connection factory
Even though IDbConnectionFactory can be resolved by the default provider it often will not be resolved this way. This is because starting with EF5 the EF NuGet packages adds a “defaultConnectionFactory” entry to the config file. This is the mechanism used
for detecting and configuring use of LocalDb without breaking existing apps and without performing the check at runtime which is slow and requires full trust. In addition, it is recommended that other providers set a default connection factory when they are
As previously discussed in other design meetings the config file entry will take precedence and no DbProviderServices implementation will be asked for a connection factory.
The options discussed for possibly changing this were:
- Leave as is
- Consistent behavior with EF5; no new stuff to understand
- Stop setting the default connection factory except for LocalDb
- In other cases the provider will supply, including for SQL Express
- This probably requires that we create an easy way for providers to to remove the entry
- Never set the default connection factory in the config and instead record LocalDb information in a different way
- When SqlProviderServices is default it the default provider it will use this LocalDb info, but it will not impact other providers
- This also helps with other issues causes by having the connection factory set automatically in the config
- However, existing apps will still have the factory set and this option is more work and creates more complexity/confusion around default connection factories
Decision: do nothing
Default provider configuration
As noted above, the default provider is implied by ordering of resolvers, which is in turn implied by ordering of provider registration. The question is whether or not to allow a more explicit way to register the default—that is, a way to register the provider
that will be at the top of the chain. For example, this could be an attribute in the config file.
We came to the decision to not do this because:
- Most people don’t need to know or care about the default provider. It most cases it currently only resolves the global spatial provider (because the connection factory is set in config) and use of multiple spatial providers in a single application combined
with use of stand-alone spatial types is not a common scenario.
- When setting the default is necessary it can still be done by ordering of registrations.
- For more than two providers having a single default is a somewhat broken abstraction since if the top provider doesn’t resolve a service (e.g. because it doesn’t support spatial) then the next in the chain will get a chance, and if this doesn’t resolve
it, then the next will get a chance, and so on.
Additional config file elements
EF6 introduced config file support for
- Global spatial provider
- Migrations SQL generator
The primary scenario for these was to allow a provider NuGet package to easily set these things. This is now handled by DbProviderServices being able to resolve additional services. They could also be used for by an application developer to override services
in the provider, but code-based configuration can still be used for this. (And we should make it easier for NuGet packages to set code-based configuration.) Also, in the future we plan to allow any service to be registered in the config file, which would make
these specific entries redundant. Therefore, we will remove support for these entries.
Previously a DbProviderServices implementation returned additional services by overriding virtual methods:
This is now handled by IDbDependencyResolver.GetService. Therefore we will remove GetExecutionStrategyFactory since it was only added in EF6 (which is not yet released). DbGetSpatialServices will be made obsolete since it has already shipped and cannot be
removed. It will still work, but the recommendation going forward is to use GetService.
Model-based conventions exploratory testing
Some additional testing work was done on model-based conventions. There were three outcomes from this:
- Some specific difficulties were identified:
- HasColumnType/HasColumnName don’t seem to be able to be used to change a column type/name
- Table is read-only
- Name doesn’t seem to work when an attempt is made to set in s-space
- We should attempt to implement one or two model conventions for things app developers or provider writers may need to do. For example, a common request is a convention that changes the naming convention for columns and tables in such a way that generated
column/table names are handled—for example, discriminator column names, IA FK column names, many-to-many table names.
- It would be useful to scan through the existing model-based conventions for any low-hanging fruit.