EF Code-First
Learning Notes Aout EF For SQL Server
Code First
here we suggest two atricles : article1:, article2:
- We create the POCO(Plain-Old-CLR-Object) classes (Business Entities) that represents the domain model in DB, then create DB based on these Classes. code sample:
public class ClubMember
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public int Occupation { get; set; }
public Nullable<decimal> Salary { get; set; }
public int MaritalStatus { get; set; }
public int HealthStatus { get; set; }
public Nullable<int> NumberOfChildren { get; set; }
}
- Then we need to create the DbContext which is responsible for the connection of DB.
Here, two key concepts are needed, that is, 1. how to call DbContext() consturctor, 2. define the DbSet class.
About the consturctor of the DbContext, we can refer to the MSDN. About the DbSet, we can refer to the code below.
public class SocialClubDbContext : DbContext
{
public SocialClubDbContext()
: base("SocialClub.DbConnection")
{
Database.SetInitializer<socialclubdbcontext>(new SocialClubInitializer());
Configuration.ProxyCreationEnabled = false;
}
public DbSet<clubmember> ClubMembers { get; set; }
}
- For the Code-First, we found these websites useful: EF Tutorial,
3.1 Conventions
3.1.1 Type discovery
The conventions for the type discovery are:
Code-First includes types defined as a DbSet property in context class.
Code-First includes reference types included in entity types even if they are defined in different assembly.
Code-First includes derived classes even if only the base class is defined as DbSet property.
3.1.2 Primary Key Convention
the default convention for primary Key is the property name is Id or
otherwise, if no such Id property is defined. the ModelValidationException will be thrown.
Exception Sample:
public class Standard
{
public Standard()
{
}
public int StdId { get; set; }
public string StandardName { get; set; }
public IList<Student> Students { get; set; }
}
StdId will throw an exception 'System.Data.Entity.ModelConfiguration.ModelValidationException' occurred in EntityFramework.dll. EntityType 'Standard' has no key defined. Define the key for this EntityType.
3.1.3 Relationship Convention
Code First infer the realtionship between the two entities using navigation property. the navigation property can be simple reference type of collection type.
Sample code:
public class Student
{
public Student()
{
}
public int StudentID { get; set; }
public string StudentName { get; set; }
public DateTime DateOfBirth { get; set; }
public byte[] Photo { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; }
//Navigation property
public Standard Standard { get; set; }
}
public class Standard
{
public Standard()
{
}
public int StandardId { get; set; }
public string StandardName { get; set; }
//Collection navigation property
public IList<Student> Students { get; set; }
}
3.1.4 Foreign key Convention
It is recommended to include a foreign key property on the dependent end of a relationship
4 Inheritance Strategy in Code-First
Even though, OO Tech include "has a" and "is a " relationship. SQLServer only support "has a " relationship between tables.Here are the three types supportting Inheritance hierarchy.
. Table per Hierarchy (TPH): This approach suggests one table for the entire class inheritance hierarchy. Table includes discriminator column which distinguishes between inheritance classes. This is a default inheritance mapping strategy in Entity Framework. TPH
. Table per Type (TPT): This approach suggests a separate table for each domain class.TPT
. Table per Concrete class (TPC): This approach suggests one table for one concrete class, but not for the abstract class. So, if you inherit the abstract class in multiple concrete classes, then the properties of the abstract class will be part of each table of the concrete class TPC
- Configure Domain Classes in Code-First
Two ways to configure your domain classes: DataAnnotations, Fluent API.
5.1 DataAnnotation
it is a simple attribute based cofiguration, which you can apply to your domain classes and its properties. full set of the attribute you can find here
Code Sample:
[Table("StudentInfo")]
public class Student
{
public Student() { }
[Key]
public int SID { get; set; }
[Column("Name", TypeName="ntext")]
[MaxLength(20)]
public string StudentName { get; set; }
[NotMapped]
public int? Age { get; set; }
public int StdId { get; set; }
[ForeignKey("StdId")]
public virtual Standard Standard { get; set; }
}
5.2 Fluent API
Fluent API configuration is applied as EF build the model from your kdomain classes. you can inject the configurations by overriding the DbContext class' OnModelCreating method as following:
Code Sample:
public class SchoolDBContext: DbContext
{
public SchoolDBContext(): base("SchoolDBConnectionString")
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Standard> Standards { get; set; }
public DbSet<StudentAddress> StudentAddress { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Configure domain classes using Fluent API here
base.OnModelCreating(modelBuilder);
}
}