Entity Framework Code First Databases
Connection strings are normal (no EDMX).
Metadata Tables
- EdmMetadata was created in EF 4.1/4.2 and stores a simple hash of the DbModel
- __MigrationHistory is created in EF 4.3 (and is marked as a system table, so hidden)
There's one table per context- so you can't have multi-tenant DbContexts for database initializers/migrations.
Initializing
In global.asax Application_Start, or DbContext.OnModelCreating add Database.SetInitializer
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(
new DropCreateDatabaseIfModelChanges<ModelContext>());
//new DropCreateDatabaseAlways<ModelContext>();
//new CreateDatabaseIfNotExists<ModelContext>();
}
Here's the EF 4.3 auto-migrations initializer:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ModelContext, Configuration>());
Except when starting a new database, you'll never want to recreate the database. You can get the DDL script.
//don't rebuild it
Database.SetInitializer<ModelContext>(null);
From EF 4.3 you can set it in app.config.
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<entityFramework>
<contexts>
<!-- shared databases - no initialization-->
<!--<context type="MyDomain.Entities.EntitiesContext, MyDomain.Entities"
disableDatabaseInitialization="true" />-->
<!-- developer database- migrate to latest version -->
<context type="MyDomain.Entities.EntitiesContext, MyDomain.Entities">
<databaseInitializer
type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[MyDomain.Entities.EntitiesContext, MyDomain.Entities], [MyDomain.Entities.Migrations.Configuration, MyDomain.Entities]], EntityFramework" />
</context>
</contexts>
</entityFramework>
If you are recreating the database in EF 4.1 and EF 4.2, you may not want the EdmMetadata table (it's off by default and marked obsolete in EF 4.3+)
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
You can check manually if the database is up-to-date with Database.CompatibleWithModel (it checks the hash in __MigrationHistory or EdmMetadata if present).
if (!Database.CompatibleWithModel(false)) Console.WriteLine("The database is out of date");
You can get the DDL script from the underlying EF ObjectContext
//just get the script manually
//you can't access this in OnModelCreating
var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext;
string script = objectContext.CreateDatabaseScript();
Testing Databases
You can create a custom IDatabaseInitializer (e.g. inheriting from a standard one) and override void Seed(TContext context)
Mapping
You can map with attributes ([Key], [Required], [Column], [Table], [ForeignKey], [DatabaseGenerated]
Components can be mapped with [ComplexType]
Or use fluent mapping:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Train>()
.Property(p => p.TrainNumber).IsRequired();
}
For configuration see System.Data.Entity.ModelConfiguration: modelBuilder.Configurations.Add(new ProductConfiguration()); You can map with EntityTypeConfiguration<T> (in the ctor.
public class ProductConfiguration : EntityTypeConfiguration<Product>
{
//configure in ctor
public ProductConfiguration()
{
Property(p => p.Code).HasMaxLength(10);
//map a foreign key column
HasRequired(l => l.Category)
.WithMany(d => d.Product)
.Map(c => c.MapKey("product_id"));
}
}