DotNetStories
In this post I would like to talk about Data Annotations and how to use them in our Code First Entity framework applications.Developers use extensively EF to build their data access layer. We have 3 development paradigms in EF. We have Database First,Model First and Code First. The last one (Code First) gains increasing popularity amongst developers.
I will use another post also found in this blog to
demonstrate Data Annotations.In order to fully
understand what I am talking about, you need to read this
post titled
Using the Code First approach when building ASP.Net
applications with Entity Framework
. It will take some time to create this application but it
is necessary in order to follow along.
With Data Annotations we can configure our domain-entity classes so that they can take best advantage of the EF.We can decorate our entity classes with declarative attributes.Let me give you an insight on how EF Code First works.EF Code First at run time, looks at the entity-domain classes and infers from them the in-memory data that it needs to interpret the queries and interact with the database.For example it assumes that any property named ID represents the key property of the class.Data Annotations "live" inside the System.ComponentModel.DataAnnotations. We do add Data Annotations to our domain classes declaratively using attributes. You can also do that imperatively using the Fluent API but this is beyond the scope of this post.
I will use these two entity classes
public class Footballer { public int FootballerID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public double Weight { get; set; } public double Height { get; set; } public List<Training> Trainings { get; set; } }
public class Training { public int TrainingID { get; set; } public int TrainingDuration { get; set; } public string TrainingLocation { get; set; } }
1) Make sure you run the application I mentioned earlier. I have already installed SQL Server 2012 Express edition in my laptop. A database is created and populated when the application runs.This happens through the magic of EF and Data Annotations.I launch SSMS connect to the instance of SQL Server 2012 Express and I browse to the database EfCodeFirstASPnet.CodeFirst.FootballerDBContext
Make sure you have a look at the tables and tables columns.
Have a look at the picture below
You can see this information through the VS 2012 IDE.Make
sure you have opened the Server Object Explorer. I connect
to the SQL Server Express Edition through that window.
Have a look at the picture below
2) Now let me explain how EF knows how to build the tables,
the columns, the data types and the various attributes (null
, not null e.t.c).You have to understand that the EF Code
First Model works with conventions.
So far everything works fine and EF Code First follows all the conventions to create the tables.
Let me break some of the conventions.I go back to the
Footballer Entity class and change
FootballerID property to AFootballPlayer
public class Footballer { public int AFootballPlayer { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public double Weight { get; set; } public double Height { get; set; } public List<Training> Trainings { get; set; } }
When I run the application again I get an error.
Please have a look at the picture below
3) The way to correct it is to add the Key attribute to the property.
The new class definition follows
public class Footballer
{
[Key]
public int AFootballPlayer { get; set;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public
double Weight { get; set; }
public double
Height { get; set; }
public DateTime
JoinedTheClub { get; set; }
public int Age {
get; set; }
public List<Training>
Trainings { get; set; }
}
Then I build and run my application.Everything works fine.Have a look at the picture below
Make sure you add a reference to the
System.ComponentModel.DataAnnotations namespace in
the class file
using System.ComponentModel.DataAnnotations;
Now let's see the effect the change has on the database. All the changes are propagated to the database through EF Code First.
Have a look at the picture below.Please note the changes in
the primary key and foreign key.
4) Now l will demonstrate the Required attribute.
I want the FirstName property to be "Required".
The way to do it is to add the Required attribute to the desired property.
The new class definition follows
public class FootballerI want the FirstName property to be "Required".
Have a look at the picture below to see the effect the new
annotation has on the database schema.The column
FirstName is not nullable.
5) Now l will demonstrate the ΜaxLength attribute.
The way to correct it is to add the ΜaxLength attribute to the property LastName.
The new class definition follows
public class Footballer
Then I run the application again and the database is
re-initialised. Have a look at the picture below. The
LastName column is not
nullable and nvarchar(40).
6) Let me show you some more attributes that are relevant to the table and columns.
I will change the name and the schema of the
Footballers table.I also change the
column name, the order and the
data type of the JoinedTheClub property.
The new class definition follows.
[Table("FootballPlayers",Schema="guest")]
public class Footballer
{
[Key,Column(Order=0)]
public int AFootballPlayer { get; set; }
[Required]
public string FirstName { get; set;
}
[Required,MaxLength(40)]
public
string LastName { get; set; }
public double
Weight { get; set; }
public double Height {
get; set; }
[Column("ContractSigned",Order=1,TypeName="date")]
public DateTime JoinedTheClub { get; set;
}
public int Age { get; set; }
public List<Training> Trainings { get; set; }
}
I build and run the application.My application compiles.
Have a look at the picture below. The database is re-initialised to reflect the changes the EF Code First propagates to the database.
There are more attributes one can use. One of them is
ConcurrencyCheck.I can annotate the LastName property
with this attribute. Have a look at the picture below. EF
now knows that this field will be marked for concurrency
cheks when we have update and delete operations.
[ConcurrencyCheck]
public string LastName { get; set; }
There are more attributes one can use to decorate with data
annotations the properties of the entity classes. I hope I
demonstrated the concept extensively.
In a future post I will demonstrate how to achieve all the
above using the EF Code Fluent API.
Hope it helps!!!