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
Create models as database tables and then generate code (models) from them
Create models as database diagrams and then generate code (models) and tables from them
Create models as code classes and then generate diagram and tables from them
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.)
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
}
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; }
}
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
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; }
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; }
}
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();
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>
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
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
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
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;
}
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 = "форум" });
}
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
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
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);
}
.Entity()
Map: Table Name, Schema
Inheritance Hierarchies, Complex Types
Entity -> Multiple Tables
Table -> Multiple Entities
Specify Key (including Composite Keys)
.Property()
Attributes (and Validation)
Map: Column Name, Type, Order
Relationships
Concurrency