Reputation: 150118
The Problem
We have an object
public class Foo
{
[Key, Column(Order = 0)]public virtual int A { get; set; }
[Key, Column(Order = 1)]public virtual int B { get; set; }
}
that needs to be mapped to an indexed view in SQL Server. Building on the approaches
EF Code First : Mapping nontable objects with Fluent API and https://stackoverflow.com/a/20887064/141172
we first created an initial migration
public override void Up()
{
CreateTable("dbo.Foos",
c => new { A = c.Int(nullable:false), B = c.Int(nullable:false) })
.PrimaryKey(t => new { t.A, t.B });
}
Then an empty migration into which we added SQL to drop the auto-generated table, and then add the index
public override void Up()
{
Sql(@"DROP TABLE Foos");
Sql(@"CREATE VIEW dbo.Foos As....");
}
finally in our DbContext, Foo is mapped to the view:
modelBuilder.Entity<Foo>().ToTable("Foos");
This worked just fine, until we added another property to Foo:
[Key, Column(Order = 2)]public int C { get; set; }
We added a new migration to redefine the view
public override void Up()
{
Sql(@"ALTER VIEW Foos ....");
}
The Alter View migration is correctly applied, but EF believes that it must create a migration to account for the new property.
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration.
When I run
Add-Migration WhatIsPending
EF generates
public override void Up()
{
DropPrimaryKey("dbo.Foos");
AddColumn("dbo.Foos", "C", c => c.Int(nullable: false));
AddPrimaryKey("dbo.Foos", new[] {"A", "B", "C" });
}
Question
Is there a better approach to mapping an object to a view, such that changes to the object are painless?
If this is the best approach, how can I inform EF Migrations that it does not need to generate the migration?
Upvotes: 3
Views: 142
Reputation: 5314
We couldn't find a way to tell EF to not create a migration, but this approach might help:
When you create the POCO, don't CreateTable()
in the migration. if EF wants to create a migration file, fine, but you can comment the code out so only your Sql(@"Create View ...");
runs.
All we had to do then was create the DbSet
for the view, not a modelBuilder.Entity
entry.
When you need to make changes, start the same way as any other table. Make changes to the POCO, then run Add-Migration
and let it create the migration for you. comment out whatever it wants to do, and add your Alter View
script in. make sure you make a corresponding one in the Down
.
This way you will just have a single migration file for each change.
Upvotes: 1