Transactions is a sequence of actions (database operations) executed as a whole:
Either all of them complete successfully
Or none of the them
Example of transaction:
A bank transfer from one account into another (withdrawal + deposit)
If either the withdrawal or the deposit fails the whole operation is cancelled
Transactions guarantee the consistency and the integrity of the database
All changes in a transaction are temporary
Changes are persisted when COMMIT is executed
At any time all changes can be canceled by ROLLBACK
All of the operations are executed as a whole
Either all of them or none of them
Some actions fail to complete
For example, the application software or database server crashes
Interference from another transaction
What will happen if several transfers run for the same account in the same time?
Some data lost after actions complete
Database crashes after withdraw is complete and all other actions are lost
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