Entity Framework Code First
Telerik Academy Alpha

 

Databases

 Table of contents

Modeling Workflows

 Modeling Workflows

  • Entity Framework supports three types of modeling workflow:

    • Database first

      • Create models as database tables

      • Use Management Studio or native SQL queries

    • Model first

      • Create models using visual EF designer in VS

    • Code first

      • Write models and combine them in DbContext

 Database First

  • Create models as database tables and then generate code (models) from them

 Model First

  • Create models as database diagrams and then generate code (models) and tables from them

 Code First

  • Create models as code classes and then generate diagram and tables from them

 Why use Code First?

  • Write code without having to define mappings in XML or create database models

  • Define objects in POCO

    • Reuse these models and their attributes

  • No base classes required

  • Enables database persistence with no configuration

    • Can use automatic migrations

  • Can use Data Annotations (Key, Required, etc.)

Code First

 Data Models

  • Bunch of normal C# classes (POCO)

    • May contain navigation properties

public class PostAnswer
{
    public int PostAnswerId { get; set; } // Primary key
    public string Content { get; set; }

    public int PostId { get; set; } // Foreign key
    public virtual Post Post { get; set; } // Navigation property
}

 Data Models

  • Another example of data class (model)

public class Post
{
    private ICollection<PostAnswer> answers;
    public Post()
    {
        this.answers = new HashSet<PostAnswer>();
    }

    public PostType Type { get; set; } // Enum, saved as an integer

    public virtual ICollection<PostAnswer> Answers
    {
        get { return this.answers; }
        set { this.answers = value; }
    }
}
public class Post
{
    public Post()
    {
        this.Answers = new HashSet<PostAnswer>();
    }

    public PostType Type { get; set; } // Enum, saved as an integer

    public virtual ICollection<PostAnswer> Answers { get; set; }
}

 DbContext

  • A class that inherits from DbContext

    • Manages model classes using DbSet type

    • Implements identity tracking, change tracking, and API for CRUD operations

    • Provides LINQ-based data access

  • Recommended to be in a separate class library

    • Don't forget to reference the Entity Framework library (using NuGet package manager)

  • If you have a lot of models it is recommended to use more than one DbContext

 DbSet

  • Collection of single entity type

  • Set operations: Add, Attach, Remove, Find

  • Use with DbContext to query database 

public DbSet<Post> Posts { get; set; }

public DbSet<PostAnswer> PostAnswers { get; set; }

 DbContext Example

using System.Data.Entity;
using CodeFirst.Models;

public class ForumContext : DbContext
{
    public IDbSet<Post> Posts { get; set; }

    public IDbSet<PostAnswer> PostAnswers { get; set; }

    public IDbSet<Category> Categories { get; set; }

    public IDbSet<Tag> Tags { get; set; }
}

 Data Interaction Example

var db = new ForumContext();

var category = new Category { Parent = null, Name = "Database course" };
db.Categories.Add(category);

var post = new Post();
post.Title = "Срока на домашните";
post.Content = "Моля удължете срока на домашните";
post.Type = PostType.Normal;
post.Category = category;
post.Tags.Add(new Tag { Text = "домашни" });
post.Tags.Add(new Tag { Text = "срок" });

db.Posts.Add(post);
db.SaveChanges();

 How to connect to SQL Server?

  • First, create context constructor that calls base constructor with appropriate connection name

public class ForumContext : DbContext
{
    public ForumContext()
        : base("ForumDb")
    { }
    // ...
}
  • Then add the connection string in app.config

<connectionStrings>
  <add name="ForumDb" connectionString="Data Source=.;Initial 
    Catalog=ForumDb;Integrated Security=True"
    providerName="System.Data.SqlClient" ></add>
</connectionStrings>

Code First Migrations

 Migrations

  • What happens when we change our models?

    • Entity Framework compares our model with the model in __MigrationHistory table

    • By default Entity Framework only creates the database and don't do any changes after that

    • Using Code First Migrations we can manage differences between models and database

 Migrations

  • Enable Code First Migrations

    • Open Package Manager Console

    • Run Enable-Migrations command

      • This will create some initial jumpstart code

    • Two types of migrations

      • Automatic migrations

        • Set AutomaticMigrationsEnabled = true;

          • ​Development ONLY!

      • Code-based (providing full control)

        • Separate C# code file for every migration

 Migration Strategies

 

  • CreateDatabaseIfNotExists (default)

  • DropCreateDatabaseIfModelChanges

    • We loose all the data when change the model

  • DropCreateDatabaseAlways

    • Great for automated integration testing

  • MigrateDatabaseToLatestVersion

    • This option uses our migrations

  • We can implement IDatabaseInitializer if we want custom migration strategy

 How to use?

  • First, enable code first migrations

    • Second, we need to tell to Entity Framework to use our migrations with code (or app.config)

Database.SetInitializer(
  new MigrateDatabaseToLatestVersion<ForumContext, Configuration>());
  • We can configure automatic migration

public Configuration()
{
    this.AutomaticMigrationsEnabled = true;
    this.AutomaticMigrationDataLossAllowed = true;
}

 Seed database

  • During a migration we can seed the database with some data using the Seed method

    • This method will be run every time (since EF 5)

    • Only for testing purposes

protected override void Seed(ForumContext context)
{
    /* This method will be called after migrating to
       the latest version. You can use the
       DbSet.AddOrUpdate() helper extension method 
       to avoid creating duplicate seed data. E.g. */

    context.Tags.AddOrUpdate(new Tag { Text = "срок" });
    context.Tags.AddOrUpdate(new Tag { Text = "форум" });
}

Configure Mappings

 Migrations

  • Entity Framework respects mapping details from two sources

    • Data annotation attributes in the models

      • Can be reused for validation purposes

    • Fluent API code mapping configuration

      • By overriding OnModelCreating method

      • By using custom configuration classes

    • Use one approach or the other

 Mappings

  • There is a bunch of data annotation attributes in System.ComponentModel.DataAnnotations

    • [Key] – specifies the primary key of the table

    • For validation: [StringLength], [MaxLength], [MinLength], [Required]

    • Schema: [Column], [Table], [ComplexType], [ConcurrencyCheck], [Timestamp], [ComplexType], [InverseProperty], [ForeignKey], [DatabaseGenerated], [NotMapped], [Index]

  • In EF 6 we are able to add custom attributes by using custom conventions

 Fluent API

  • By overriding OnModelCreating method in DbContext class we can specify mapping configurations

protected override void OnModelCreating(
  DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Student>().HasKey(x => x.Id);
    modelBuilder.Entity<student>().Property(x => x.Name)
      .IsUnicode(true);
    modelBuilder.Entity<Student>().Property(x => x.Text)
      .HasMaxLength(255);

    base.OnModelCreating(modelBuilder);
}

 Fluent API

  • .Entity()

    • Map: Table Name, Schema

    • Inheritance Hierarchies, Complex Types

    • Entity -> Multiple Tables

    • Table -> Multiple Entities

    • Specify Key (including Composite Keys)

 Fluent API

  • .Property()

    • Attributes (and Validation)

    • Map: Column Name, Type, Order

    • Relationships

    • Concurrency

context.Questions.ToList();

[Databases] Entity Framework Code First

By telerikacademy

[Databases] Entity Framework Code First

  • 1,431