Introduction
This article will explore some interesting and important constructs of the Entity Framework. We will dig into some core components of the Entity Framework. We will also explore how EF manages Conceptual, Logical, and Physical schema perfectly without any conflicts.
Background
Entity Framework is an open-source Object-Relational Mapping (ORM) technique, first released in August 2008 by Microsoft.
ORM is a technique to map database objects to Object-Oriented Programming Objects to let the developer focus on programming in an Object-Oriented manner.
It was very painful for developers to create schema, tables, views, and so on in a database and it was also a time-consuming job for developers. However before the Entity Framework another powerful ORM existed and is still a choice of many developers, it is
NHibernate.
The Entity Framework was really developed to save developer's time and the burden of boring work.
EF is generally suitable to work with ADO.NET and SQL. To be honest I was not aware of EF working with various databases and I was surprised. Because we generally see blogs or tutorials about EF to SQL but actually EF works with the following databases apart from SQL Server:
- MySQL
- SQLite
- PostgreSQL
- Oracle
- DB2
- Informix
- Firebird
It works with various databases however it has some limitations. You can find good information here:
A list of Entity Framework providers for various databases.
Using Visual Studio
Let's start with a quick example using Visual Studio. Create a console application and add an ADO entity data model.
Name it MyEFModel.edmx (EDM is the acronym of an Entity Data Model).
Once you click on add it will take you to the next window as below:
You can also choose an empty model and generate the database since EF supports both operations (Code First and Schema First).
To make things simple we will use the first option “Generate from database”. If you want to learn more about the Schema first approach, you can refer to:
Model-First in the Entity Framework 4.
The next step is to choose the database and tables; here I have created two tables Member and Activity that we will use to generate Entities.
Choose the connection and the next window will look like:
The Connectionnstring and metadata will depend on your system configuration and will be saved in the configuration file.
Next, the window will ask you to choose the database objects along with two options.
- Pluralize or singularize generated object name: basically, add or remove s or es in object names.
- Include a foreign key column in the model: this property is used for including relations among tables.
Select tables only and click on finish. Once you do that you will get a nice view of your tables (behind the scenes) as in the following:
You can see the linking among entities (as tables in the database).
Now to make it perfect let's change the ID of the member entity to MemberID, it's quite simple; just click on the ID property and rename it.
Now we can perform operations on the tables using the TestDBEntities class.
For example, to read data from the Member table we can use:
- using (TestDBEntities entities = new TestDBEntities())
- {
- var member = entities.Member.FirstOrDefault(m=>m.MemberID==2);
-
- Console.WriteLine(string.Format("Member Name :{0}\n Mobile:{1}", member.Name, member.Mobile));
-
- }
Note: ID became MemberID now (it will be managed by the conceptual schema).
Now in this article, I am not going into depth about how to apply CRUD operations over EF since you will find many, and trust me it's quite easy.
Entity Framework Generated Classes
If you look into the classes generated by the EF you will see the following two separate groups of files:
- MyEFModel.Context.tt: It contains the core context class that is an extended form of the DbContext class.
- MyEFModel.tt: It usually contains classes where the class name will be the same as the table name in the database and the property name is the same as in the related table.
You will also find an interesting thing here that the class generated for the Member table will look like:
- public partial class Member
- {
- public Member()
- {
- this.Activities = new HashSet<Activity>();
- }
-
- public string Name { get; set; }
- public string Mobile { get; set; }
- public int MemberID { get; set; }
-
- public virtual ICollection<Activity> Activities { get; set; }
- }
The public virtual ICollection<Activity> Activities { get; set; } property is for the foreign key relation with the Activity table and the point of interest is the “public int MemberID { get; set; }” property. This is because we changed the property earlier.
And the activity class will look as expected.
- public partial class Activity
- {
- public string Action { get; set; }
- public Nullable<System.DateTime> Time { get; set; }
- public int ID { get; set; }
- public int MemberID { get; set; }
-
- public virtual Member Member { get; set; }
- }
- // And finally the TestDBEntities will look like
- public partial class TestDBEntities : DbContext
- {
- public TestDBEntities() : base("name=TestDBEntities")
- {
- }
-
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
- throw new UnintentionalCodeFirstException();
- }
-
- public DbSet<Activity> Activity { get; set; }
- public DbSet<Member> Member { get; set; }
- }
Mapping and configuration
You must be wondering about the clean code, how it is possible that everything is working with the clean code without any extra mapping.
DbContext Class
Actually, the DbContext class that is quite similar to ObjectContext is a combination of the “Unit Of Work” and “Repository” patterns that has three important methods, the Set() method that returns a DbSet instance, ValidateEntity method for validating an entity, and most important is the SaveChanges() method that sends changes to the database.
Configuration files
As I said in the intro there are three layers that represent a good schema to work with an RDBMS (a data-driven approach).
Entities are basically the classes on the client-side that need to be mapped on the database at runtime. Now here we need all these configuration files to map our entity classes to the database in a proper way, so we could avail of the RDBMS features.
Any system that follows a data-driven approach uses three models known as 1. “Conceptual model”, 2. “Logical model”, 3. “Physical model”.
Let's have a brief discussion on these models:
- Conceptual Model: It defines the tables (entities) and their relationship.
- Logical Model: It provides the relationships (mappings) among the tables (entities) using foreign key relationships.
- Physical Model: It specifies the storage, partitions, and indexing details of the database.
The Entity Framework follows this pattern strictly and it creates 3 files with the extensions *.csdl, *.msl, and *.ssdl.
When we compile our project, the EF generates these files behind the scenes. Strictly speaking actually the .edmx file is itself an XML-based file that contains details about the linking among entities and the preceding specified files.
Why these files are required
To inspect these files you must compile your project once. Go to the Solution Explorer and click on "Show all files" and then navigate to the debug folder inside the obj folder and you will find the following files.
The
edmxResourcesToEmbed folder contains three files that we were talking about. Let's go through these files.
To maintain a data-driven approach the EF generates the following files.
- *.csdl: This configuration file has the conceptual model of the entities.
And will look like:
It specifies the foreign key relationship and contains a Scheme tag at the start.
- *.msl: This configuration file has the mapping layer. Remember that I changed the ID column to MemberID. To the best of my knowledge, this is an optional file and if we do not configure any mapping, the EF will not create it. This file will look like:
- * ssdl: This configuration file is the final and important one because this is all about the physical layer. It has the information of the data provider and similar members like *.csdl file.
Apart from these files the *.EDMX file also contains a description put it in these files at compile time.
All together
To read and access settings from these files the base library of EF has the following parsers:
- (System.Data.Entity.Edm.Parsing.Xml.Internal.Csdl,
- System.Data.Entity.Edm.Parsing.Xml.Internal.Ssdl,
- System.Data.Entity.Edm.Parsing.Xml.Internal.Msl)
and serializers:
- (System.Data.Entity.Edm.Serialization.Xml.Internal.Ssdl,
- System.Data.Entity.Edm.Serialization.Xml.Internal.Csdl and
- System.Data.Entity.Edm.Serialization.Xml.Internal.Msl)
Namespaces where it has defined constants for attributes to read files optimally.
And this is the reason why the connectionsting in the configuration file has a metadata attribute like:
metadata=res://*/MyEFModel.csdl|res://*/MyEFModel.ssdl|res://*/MyEFModel.msl;
When we run our application the C# compiler puts all of it together and we get to work with a nice and handy API known as “Entity Framework”.
Conclusion
Before writing this I have gone through many articles and blogs written about the Entity Framework and have provided this interesting abstraction to you.
I hope by now if you see any error or warning generated by the EF you will definitely look into the *.EDMX , *.csdl,*.ssdl, and *.msl files and see where the issue is.
Note: you can also see the description of the error if you are getting any when generating an entity. You just need to open the *.edmx file with an XML editor.
Your suggestions and feedback are most welcome.