API Review: Code Based Config & Dependency Resolution

The purpose of API Review meetings is to go over new API surface one class/member at a time to ensure we have a consistent and high quality API. We look at how classes are structured, which members are public as well as the names of classes, members and parameters.

Namespace

  • Move all types into System.Data.Entity.Infrastructure.DependencyResolution
    • Except DbConfiguration which will go in root namespace
  • We considered .Configuration namespace but that causes issues with the Configuration class from .NET

 

System.Data.Entity.Config.DbConfiguration

  • Move to the root namespace - we think this will be used often

 

  • Remove Add/Set prefixes from the methods
    • Exceptions are AddDepdendencyResolver and SetConfigurations since they aren't about registering config
    • They were all really Set anyway (except interceptors where you can have multiple instances registered)

 

  • We could make it more fluent and/or group methods up into sub-properties
    • Discussed a few options but decided to keep it simple

 

  • Remove GetService (since it's easy to access off GetServices method (was missed when we added it to the resolver)

 

  • For tooling it would be good to have a way to load config from an assembly
    • We should add some basic hooks in EF6 (make it easy to find the config and load it)

 

  • Remove named delegate types and just use Funcs (i.e. HistoryContextFactory, CommandLoggerFactory, etc.)
    • We added these to make it easier to understand what you needed to pass to methods that need a factory
    • They don't really make it any easier though, intellisense is basically the same as for Funcs

 

  • Remove 'Db' from registration method names when Db is part of type name
    • We typically use Db to identify commonly used EF/data related types
    • These methods are on DbConfiguration so it's not needed

 

  • When we require things like factories we sometimes use an interface and sometimes Funcs
    • For straight up factories we should just use Funcs (i.e. remove ModelCacheKeyFactory etc.)
    • We should also remove the work Factory from the registration method name
    • For resolvers/lookups, etc. we should continue to use an interface

 

  • When resolving a service that was registered as a Func you typically pass the Func as the type to resolve
    • MigrationsSqlGenerator is the exception to this - we should change it so you need to specify the Func

 

  • Rename OnConfigLocking to Loaded (since it's on the DbConfiguration class anyway)
    • Loaded is a more common term, folks don't really need to understand the locking etc.

 

  • AddSecondaryResolver method if confusing and would be good to try and hide away
    • See if we can make it internal?

 

  • Discussed trying to move AddDepencyResolver since this API is now mostly scoped to the sugar methods for configuration
    • Ultimately decided to leave it here as we think it makes sense

 

  • DefaultSpatialServices should just be an overload of SpatialServices that doesn't have a key (same as a null key)
    • Add docs to intellisense that we fall back to one that is registered without a key

 

  • Drop the 'Default' on DefaultConnectionFactory
    • This was done to be consistent with the old Database.DefaultConnectionFactory API
    • Not having Default is more consistent with the rest of this new API though

 

  • SetViewAssemblyCache is going away as part of ongoing View Generation work

 

System.Data.Entity.Config.DbConfigurationEventArgs

  • Rename to DbConfigurationLoadedEventArgs

 

  • See if we can make AddSecondaryResolver internal here too
    • Check we have template method on DbProviderServices

 

  • Rename ResolverSnapshot to DependencyResolver
    • The caller doesn't really need to know that it's a snapshot

 

System.Data.Entity.Config.DbConfigurationTypeAttribute

  • No changes needed here

 

System.Data.Entity.Config.ExecutionStrategyResolver<T>

  • Make this internal
    • It doesn't provide much value and is very easy to implement if you wanted
    • Most folks will just use the DbConfiguration API

 

System.Data.Entity.Config.IDbDependencyResolver

  • No changes needed here

 

System.Data.Entity.Config.IDbDependencyResolverExtensions

  • Remove the I from the name - it's not an interface

 

System.Data.Entity.Config.ResolverChain

  • Make this internal

 

System.Data.Entity.Config.SingletonDependencyResolver<T>

  • Make this internal
    • The main scenario for writing resolvers is wiring up existing IoC container, in which case you wouldn't use this class

 

System.Data.Entity.Config.TransientDependencyResolver<T>

  • Make this Internal

 

System.Data.Entity.Infrastructure.DbProviderNameAttribute

  • Remove this attribute
    • It's handy for making things look like they are simpler… but it makes things more confusing in the long run

 

  • Is there any way we could remove the need to provide the Provider Invariant Name?
    • Not really and the invariant name is a well-known concept
    • We will provide static constants for the SQL/SQL Compact ones in our providers

 

System.Data.Entity.Core.Common.DbProviderServices

  • No changes needed here

 

IManifestTokenService

  • Rename to IManifestTokenResolver
    • Also change method name on DbConfiguration

 

  • Rename method to ResolveManifestToken
    • We discussed just using Resolve but specific names are nice because they let you easily implement multiple interfaces on a single type. Not necessarily a key scenario on this type, but a general rule we want to follow.

 

IDbModelCacheKeyFactory

  • Remove this class and replace with a Func

 

IDbProviderFactoryService

  • Rename to IDbProviderFactoryResolver

 

  • Rename method to ResolveProviderFactory()

 

Exceptions

Changes are highlighted…

 

DefaultConfigurationUsedBeforeSet

The default DbConfiguration instance was used by the Entity Framework before an attempt was made to set an instance of '{0}'. The '{0}' instance must be set at application start before using any Entity Framework features or must be registered in the application's config file. See http://go.microsoft.com/fwlink/?LinkId=260883 for more information.

ConfigurationSetTwice

An instance of '{0}' cannot be set because an instance of '{1}' is already being used. Only one DbConfiguration type can be used in an application. The DbConfiguration type to use cannot be changed once it has been set. See http://go.microsoft.com/fwlink/?LinkId=260883 for more information.

ConfigurationNotDiscovered

The default DbConfiguration instance was used by the Entity Framework before the '{0}' type was discovered. An instance of '{0}' must be set at application start before using any Entity Framework features or must be registered in the application's config file. See http://go.microsoft.com/fwlink/?LinkId=260883 for more information.

SetConfigurationNotDiscovered

An instance of '{0}' was set but this type was not discovered in the same assembly as the '{1}' context. Either put the DbConfiguration type in the same assembly as the DbContext type, use DbConfigurationTypeAttribute on the DbContext type to specify the DbConfiguration type, or set the DbConfiguration type in the config file. See http://go.microsoft.com/fwlink/?LinkId=260883 for more information.

AddHandlerToInUseConfiguration

The Entity Framework was already using a DbConfiguration instance before an attempt was made to add a 'Loaded' event handler. 'Loaded' event handlers can only be added as part of application start-up before the Entity Framework is used. See http://go.microsoft.com/fwlink/?LinkId=260883 for more information.

CreateInstance_BadDbConfigurationType

The type '{0}' does not inherit from '{1}'. Entity Framework code-based configuration classes must inherit extend from '{1}'.

MultipleConfigsInAssembly

  • Put quotes around {x}
  • Check attribute works before changing text

The assembly {0} contains more than one type derived from {1}. Either use DbConfigurationTypeAttribute on the DbContext type to specify the DbConfiguration type, define the DbConfiguration type to use in the application's config file, or ensure that the assembly contains at most one type derived from {1}.

DbConfigurationTypeNotFound

The DbConfiguration type '{0}' specified in the application config file could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260883 for more information.

DbDependencyResolver_InvalidKey

No '{0}' instance was passed to the IDbDependencyResolver.GetService method. A '{0}' instance must be supplied when attempting to resolve an '{1}' dependency.

ConfigurationLocked

The call to DbConfiguration.{0} failed because the configuration is locked. The protected methods and properties of DbConfiguration are intended to be called only from the constructor of a class derived from DbConfiguration and cannot be called after the DbConfiguration object is in use.

DbDependencyResolver_NoProviderInvariantName

No name was passed to the IDbDependencyResolver.GetService method. The provider invariant name must be supplied when attempting to resolve a '{0}' dependency.

DbConfigurationTypeInAttributeNotFound

The DbConfiguration type '{0}' specified in the DbConfigurationTypeAttribute constructor could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260883 for more information.

EF6Providers_ProviderTypeMissing

The Entity Framework provider type '{0}' registered in the application config file for the ADO.NET provider with invariant name '{1}' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

EF6Providers_InstanceMissing

The Entity Framework provider type '{0}' did not have a static property or field named 'Instance'. Entity Framework providers must declare a static property or field named 'Instance' that returns the singleton instance of the provider.

EF6Providers_NotDbProviderServices

The 'Instance' member of the Entity Framework provider type '{0}' did not return an object that inherits from 'System.Data.Entity.Core.Common.DbProviderServices'. Entity Framework providers must inherit from this class and the 'Instance' member must return the singleton instance of the provider. This may be because the provider does not support Entity Framework 6 or later; see http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

EF6Providers_NoProviderFound

No Entity Framework provider found for the ADO.NET provider with invariant name '{0}'. Make sure the provider is registered in the 'entityFramework' section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

EntityClient_InvalidStoreProvider

  • This is an old message from an early version of EF.
    • Come up with a new message that uses concepts from messages that we reviewed

The specified store provider cannot be found in the configuration, or is not valid.<o:p =""><o:p>

Last edited Jul 11, 2013 at 10:28 PM by RoMiller, version 10