I am migrating a legacy database to a new database which we need to access and "manage" (as oxymoronic as it might sound) primarily through Entity Framework Code-First.
We are using MS SQL Server 2014.
The legacy database contained some tables with computed columns. Typical GUID and DateTime stuff.
Technically speaking, these columns did not have a computed column specification, but rather where given a default value with
NEWID()
andGETDATE()
We all know that it is very easy to configure the DbContext
to deal with those properties as follows:
modelBuilder.Entity<Foo>()
.Property(t => t.Guid)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
modelBuilder.Entity<Bar>()
.Property(t => t.DTS)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
The above would instruct the Entity Framework to ignore submitting any supplied values for such properties during INSERTs
and UPDATEs
.
But now we need to allow for import of legacy records and maintain the OLD values, including the PRIMARY KEY, which is marked as
IDENTITY
This means we would have to set the
Id
,Guid
andDTS
properties toDatabaseGeneratedOption.None
while inserting those records.For the case of
Id
, we would have to somehow executeSET IDENTITY_INSERT ... ON/OFF
within the connection session.And we want to do this importing process via Code-First as well.
If I modify the model and "temporarily" and set those properties to
DatabaseGeneratedOption.None
after the database has been created, we would get the typical:The model backing the context has changed since the database was created. Consider using Code First Migrations to update the database.
I understand that we could generate an empty coded-migration with
-IgnoreChanges
so as to "establish" this latest version of the context, but this wouldn't be an acceptable strategy as we would have to be run empty migrations back-and-forth solely for this purpose.
Half an answer:
We have considered giving these properties nullable types, i.e.
public class Foo
{
...
public Guid? Guid { get; set; }
}
public class Bar
{
...
public DateTime? DTS { get; set; }
}
While caring about the default values in an initial DbMigration
:
CreateTable(
"dbo.Foos",
c => new
{
Id = c.Int(nullable: false, identity: true),
Guid = c.Guid(nullable: false, defaultValueSql: "NEWID()"),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Bars",
c => new
{
Id = c.Int(nullable: false, identity: true),
DTS = c.Guid(nullable: false, defaultValueSql: "GETDATE()"),
})
.PrimaryKey(t => t.Id);
The Question:
But the question remains: Is there a way to switch between DatabaseGeneratedOption.Identity
, DatabaseGeneratedOption.Computed
and DatabaseGeneratedOption.None
at runtime?
At the very least, how could we turn DatabaseGeneratedOption.Identity
on/off at runtime?