The ObjectContext is a base class for all Entity Framework models. While there exists a rich API for interacting with a model, the ability to adapt the underlying schema to the (potentially varying) run-time environment presents a serious shortcoming for many production applications. These variances can potentially involve myriad considerations, from a change in database owner to modified table names (often by a production-specific prefix). This can have a serious impact on large-scale deployment of applications using the Entity Framework (those familiar with my DotNetNuke-related work will immediately understand this consideration, where a run-time environment may be configured to use an arbitrary database owner or table prefix).
To remedy this issue, I have developed an adaptive framework that converts an Entity Framework model generated by the Visual Studio designer into a highly configurable result. This framework is designed to be flexible, extendable, and highly customizable.
My goals for any satisfactory solution were as follows:
- Run-time adjustment of an Entity Framework EDMX model, including:
- Connection-based adaptation (e.g. use of a runtime-specified connection string)
- Run-time adjustment of model schema, including:
- Adjusting data-level table prefixes or suffixes
- Adjusting the owner of database objects
- Continued use of the Visual Studio Model designer
- No tedious changes in the compiler-generated code
- Continued use of an assembly-embedded EDMX model (and thereby no additional or external schema deployment files)
It is unfortunate that the object model exposed by the Entity Framework is so frustratingly difficult to extend. The underlying metadata are overwhelmingly read-only (and, frustratingly, many potentially useful classes are either internal or sealed). Indeed, it seemed that there was no simple remedy to the problem at hand.
My solution utilizes the following approach:
- A Connection adapter is used to walk a model (and optionally adapt a connection string based upon a run-time environment) [Goal 1].
- During the model walk, a dependency-injected model adapter is utilized to adapt various attributes of the model (currently storage, mapping, and association) [Goal 2]. Walking is reasonably inexpensive, and since the models are cached by type, performance is not affected.
- The framework requires only a change in base class to an AdaptingObjectContext (which itself derives from an ObjectContext). This allows the Visual Studio editor to continue to be utilized, and no direct EDMX manipulation is required (though, frustratingly, the base class of an entity model is not adjustable through the Visual Studio UI, necessitating a change in the code-generated file) [Goal 3, 4, 5].
I use dependency injection to adapt attributed entities (database, table, and function names) into their adapted counterparts. Additional adapters could easily be constructed for other domains, should any arise (to illustrate this point, a NonTransformingAdapter is included in the release, which performs no transformations).
As is all of my DotNetNuke-related work, this framework is available under a liberal open-source license for ready public consumption (and extension). Though the content herein is protected under the license below, be sure to consult the project license (New BSD) for integration-related details.
As always, feedback is appreciated.