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

x

We use cookies to ensure the best possible experience on our website. Detailed information on the use of cookies on this site is provided in our Privacy and Cookie Policy. Further instruction on how to disable our cookies can be found there.