Applications

Entity Framework Code First

Entity Framework Code First

Pluralsight course Entity Framework 4.1 – Code First by Julie Lerman
General Info
Code first is a very convention heavy method of describing how an application should interact with a database. It is used in place of a .edmx model file and typically implemented when there is no database to begin with, but you may also map the domain classes to a existing data source. Since there is no physical model or XML file to read at start-up the application must create the in-memory metadata directly from the class definitions. Data annotations and fluent API’s are used in addition to the POCO classes to achieve the desired database architecture and functionality.
Conventions
  • Primary Keyby default Entity Framework will look for the class property Id or ClassName+Id to use as the primary key when mapping to the database.
    public int Id { get; set; }
    public int ClassName+Id { get; set; } 
  • Foreign Key – EF automatically establishes relationships, when one class has a domain class property, that property is set to the foreign key.
  • Virtual Keyword – prefix the domain class property with the virtual keyword to enable lazy loading and have navigation to the related object.
    public virtual ClassName ClassName { get; set; } 
  • Connection String – if not specified EF will create the database in SQL Express. Also, until an insert happens, the database will not be generated even if it is seeded.
DbContext: The Meat and Potatoes! 
If the domain classes are like tables, then the class that inherits from DbContext is like the database.
  • Defining a table – every domain class that is to be persisted in the database must be a property of the context class.
    public DbSet<ClassName1> ClassName1 { get; set; }
    public DbSet<ClassName2> ClassName2 { get; set; }
    //other domain classes…
  • Database Initialization – There are three classes in the System.Data.Entity namespace which control how Entity Framework behaves when the DbContext model structure changes.
    CreateDatabaseIfNotExist<ContextClass> //default strategy
    DropCreateDatabaseIfModelChanges<ContextClass>
    DropCreateDatabaseAlways<ContextClass> 
  • Seeding the database – For each of the database initialization strategies there is an overridable method called Seed which takes a context parameter.
    protected override void Seed(ContextClass context)
            {
                //create entities and add them to the database
                base.Seed(context);
            }
  • Fluent API – A more robust way of defining the model’s mapping to the database. Data annotations are more concise, but just a subset of what fluent API’s can do. Fluent API statements are placed in the overridable OnModelCreating method in the DbContext class and take a DbModelBuilder parameter. Some fluent API’s are composable.
    • Defining a non-conventional Id property (see Primary Key convention above)
      modelBuilder.Entity<ClassName>().HasKey(x => x.PropertyName); 
    • Defining the table name, when table and class don’t match
      modelBuilder.Entity<ClassName>().ToTable("TableName"); 
    • Entity Splitting – Split the domain class into multiple database tables, the tables will share a primary key (must be one-to-one)
      modelBuilder.Entity<ClassName>().Map(mc =>
          {
              mc.Properties(p => new {p.Id, /*other properties for Table 1*/});
              mc.ToTable("Table1Name");
          }).Map(mc =>
              {
                  mc.Properties(p => new {p.Id, /*other properties for Table 2*/});
                  mc.ToTable("Table2Name");
              });
    • Table Splitting – Split the database table into multiple domain classes, first map entities to same table, then configure the bi-directional relationship
      modelBuilder.Entity<PrincipalClassName>().ToTable("SameTableName");
      modelBuilder.Entity<
      ExtendedClassName>().ToTable("SameTableName");
      modelBuilder.Entity<
      PrincipalClassName>().HasRequired(a => a.ExtendedClassName).WithRequiredPrincipal(); 
    • Many-to-Many Relationships – Each class involved will have each other class as one of its properties wrapped in ICollection<>, remember to include the virtual keyword if you want navigation.
      modelBuilder.Entity<Class1Name>().HasMany(p => p.Class2Name).WithMany(t => t.Class1Name)
                  .Map(mc =>
                      {
                          mc.ToTable("Class1JoinClass2");
                          mc.MapLeftKey("Class1Id");
                          mc.MapRightKey("Class2Id");
                      }); 
    • More fluent API’s here.
 
Data Annotations and Code First
The following is not a comprehensive list of data annotations, just some of the non-trivial, note worthy ones.
  • [ConcurrencyCheck] – SQL will look for entries by Id and the property with the [ConcurrencyCheck] attribute when doing updates or deletes. An exception is thrown if nothing come back from the query.
  • [Timestamp] – This has the same functionality as a concurrency check attribute but is used on a property of type Byte[] and captures the date and time the entry was modified. Also known as row version.
  • [DatabaseGenerated(DatabaseGeneratedOption.Computed)] – Allows a database formula to define the value of the field. Best used with established/existing databases, doesn’t work well with code first.
  • [ComplexType] – Attribute at the class level. Complex classes do not have an Id property. When included as a single property in the "parent" class, the complex class’s fields are incorporated into the "parent" class’s table.
    • Parent Table
      -Field 1
      -Field 2
      -…
      -ComplexClass_Field 1
      -ComplexClass_Field 2
      -…
 
  • [InverseProperty("PropertyName")] – Defines a bi-directional relationship, when two classes have multiple relationships among themselves.
Inheritance Hierarchy
Table Per Hierarchy – When one domain class inherits from another, Entity Framework assumes this to be a TPH structure. Thus, each derived class is placed in the same database table as the base class and a discriminator field is added along with the other fields from the derived class.
Table Per Type – To configure for this structure, explicitly define what tables to map to (for each member of the hierarchy) via fluent API’s (see above). The result is a TPT structure, and an automatic benefit is that Entity Framework will generate the derived class’ Primary Key and Foreign Key fields to link back to the base class table.

Leave a Reply