The establishment of the .NET framework as the default intellectual platform for Microsoft software development has enabled the creation of great software by all developers alike – including my 10 year old son! Equally important, the platform has matured with the same rhythm as it has expanded. Today we enjoy the beginning of a revolution in software development via software modeling. ADO.NET Entity Framework makes possible the modeling of data as a software artifact. The implications for developer productivity are tangible immediately with the integration into Visual Studio, SQL Server and ultimately other databases.
When we talk about the Entity Framework we’re really referring to two separate things:
- The Entity Data Model (EDM)
- The Entity Framework
Entity Data Model (EDM)
The EDM is a set of layers that make up your application’s model, as well as it’s mapping to an underlying data store.
• It is made up of three parts:
- CSDL (Conceptual Schema Definition Language)
- MSL (Mapping Specification Language)
- SSDL (Storage Schema Definition Language)
This separation of concerns allows great flexibility:
- Model your application the way you want regardless of the state/structure of its underlying data store
- Normalize your database as much as you need without worrying about affecting the interface of the application’s object model
The EDM represents a re-useable application model that can be leveraged from within many applications/environments and persisted across numerous databases. The Entity Data Model is RDMS agnostic, and numerous database vendors are currently developing providers:
- Oracle, DB2, MySQL, PostgreSQL, VistaDB, SQLite, Sybase, Informix, etc.
The Entity Data Model consists of three main concepts:
- Entities, which represent your domain objects.
- Associations, which represent a relationship between two entities.
- Functions, which represent stored procedures or UDFs in your database that can be mapped to model-level functionality.
Because there will be plenty of situations where you’ll need to use stored procedures, the Entity Data Model allows you to map functions in your model to a store procedure in your database. This is useful because you can leverage a stored procedure without having to write ADO.NET code to call it, you can simply call a function on your model.
The Entity Framework is a set of services that allow you to consume an EDM from within your applications:
- Entity Client
- Entity SQL
- Object Services
- Entity SQL
- LINQ To Entities
The Entity Client is an Entity Framework “port” of the familiar object model of classes used in traditional ADO.NET programming, including:
Because of this fact it makes it a prime choice for developers migrating to the Entity Framework from ADO.NET. Just like traditional ADO.NET, your queries are returned as sequential text-based data that can iterated over using an EntityDataReader. This is great for performance, but lacks the rich object model that was created as part of your EDM.
Entity Client gives you read-only access to your EDM. If data modification is required, you’ll have to use Object Services, which we discuss below. When using Entity Client, your queries are written using Entity SQL.
Entity SQL is a query language that is syntactically very similar to SQL, but serves the sole-purpose of querying an EDM.
Because it is meant for querying your EDM, this means your queries are written against your conceptual model, not your underlying data store.
This higher-level abstraction allows you to write a textual query that is database agnostic. The translation from Entity SQL to T-SQL or PL/SQL (or whatever flavor your underlying data uses), is done by the selected ADO.NET Provider.
Below we see a simple example that shows the same query written in T-SQL as well as Entity SQL.
Notice that in Entity SQL we don’t have to do any joins, because the notion of relationships is first-class in our conceptual model. As a result, our query is half the size as the T-SQL version.
Notice the use of the “Length” function in our Entity SQL example. This is called a “Canonical Function”, which is a high-level abstraction of a database function that will be translated into its respective database-specific flavor by your underlying provider.
While the Entity Client API is great and provides great performance, it lacks the use of our created object model, as well as the ability to update data in our model.
- The Object Services API sits on top of Entity Client, and provides object materialization on top of our queries.
- This means that instead of getting text-based results, we get back a collection of CLR objects that we can easily work with.
The two mains components of the Object Services taxonomy are: ObjectContext, and ObjectQuery<T>
- ObjectContext is equivalent to an EntityConnection, and is what manages our connection to the EDM as well as provides crucial services for working with our data.
- ObjectQuery is equivalent to an EntityCommand and represents a single query executed against our EDM that is manifested back as strongly-typed objects.
• Object Services allows you to write queries using two flavors:
- Entity SQL
- LINQ To Entities
The same Entity SQL queries you would write using Entity Client can be leveraged with Object Services, but with the added benefits you get with the higher abstraction level (i.e. object materialization).
While Entity SQL is great for scenarios that require a dynamic query, or greater control over your query’s shape, you’re still working with a string that is error-prone. In addition to Entity SQL, Object Services allows you to write your queries against it in LINQ which provides you with strong-typing, error-checking, and a higher level of abstraction from Entity SQL.
In addition to object materialization, Object Services provide you with this benefits/services:
- Unit of work
- Your ObjectContext represents your unit of work, which aggregates all changes made to all entities attached/contained in it, so that when you want to push those changes back to the server, you can do so in a single batch.
- Identity tracking
- The ObjectContext keeps track of the entities you’ve queried for by key, so that if you later request the same entity (by key), using the same ObjectContext instance, it will return you the instance it already has instead of re-hitting the database.
- Eager/explicit loading
- The Entity Framework doesn’t pre-load any relationship properties for you. If you want to query an entity as well as some of its related entities, you’ll need to explicitly request that by performing a “span” using the Include method of the ObjectQuery<T> class. Alternatively, you can call the Load method on your entity’s relationship property.
Via the EDM, and its natural integration into the Visual Studio designer, developers can enable basic mapping scenarios. Developers can also modify the way their application views the model independently of your database.
With the query options built into the framework, applications can consume the EDM via Entity Client using Entity SQL; or via Object Services for mapping the model into objects with identity mapping, change tracking, and eager loading functions.