c# 4.0 - Seeding data will not work when schema changes with Code First when using migrations -
okay using entity framework 6.1 , attempting code first seeding. have drop intializer works. want use database migration have set , works. until normalize out table , try seed primary key error.
basically in context when uncomment out changes in 'todo' section , schema changes primary key violation when attempting population of newly normalized out table. work initializer drop always, want migration data table , not drop database everytime make changes in case want rollback ever. have tried changing attribute of 'personid' identity , none , identity. caveat if set 'identity' work values keep incrementing higher values each time 1,2,3,4 5,6,7,8;etc. if set none works first time , when split in mapping , normalized blows up. have tried custom dbcc commands , not either, setting dbcc reseed 2 new tables not it. if has no idea seeding new table when being done explicitly.
does know how seeding process model can handle if normalize out mapping of object multiple tables? trying bunch of different patterns , getting fast.
so poco object
public class person { [databasegenerated(databasegeneratedoption.none)] public int personid { get; set; } [column(typename = "varchar")] [required] [maxlength(32)] public string firstname { get; set; } [column(typename = "varchar")] [required] [maxlength(32)] public string lastname { get; set; } [column(typename = "varchar")] public string overlylongdescriptionfield { get; set; } }
context code first:
public class easycontext : dbcontext { public easycontext() : base("name=easyentity") { //database.setinitializer<easycontext>(new easyinitializer()); database.setinitializer(new migratedatabasetolatestversion<easycontext, migrations.configuration>("easyentity")); } public dbset<productorder> productorder { get; set; } public dbset<person> person { get; set; } public dbset<product> product { get; set; } public dbset<audit> backup { get; set; } protected override void onmodelcreating(dbmodelbuilder modelbuilder) { modelbuilder.hasdefaultschema("dbo"); modelbuilder.conventions.remove<pluralizingtablenameconvention>(); modelbuilder.conventions.remove<manytomanycascadedeleteconvention>(); //todo let's normalize out long descriptive field //modelbuilder.entity<person>() //.map(m => //{ // m.properties(p => new { p.firstname, p.lastname }); // m.totable("person"); //}) //.map(m => //{ // m.properties(p => new { p.overlylongdescriptionfield }); // m.totable("persondescription"); //}); } }
initializer dropcreatealways:
public class easyinitializer : dropcreatedatabasealways<easycontext> { protected override void seed(easycontext context) { seedingvalues.seedingfordatabasedrop(context); base.seed(context); } }
configuration migrations:
internal sealed class configuration : dbmigrationsconfiguration<easyentity.easycontext> { public configuration() { automaticmigrationsenabled = true; automaticmigrationdatalossallowed = true; contextkey = "easyentity.easycontext"; } protected override void seed(easycontext context) { seedingvalues.seedingwithoutdatabasedrop(context); base.seed(context); } }
base seeding class:
internal static class seedingvalues { public static void seedingfordatabasedrop(easycontext context) { baseseed(context); } public static void seedingwithoutdatabasedrop(easycontext context) { context.person.clearrange(); baseseed(context); } private static void baseseed(easycontext context) { ilist<person> persons = new list<person> { new person { personid = 1, firstname = "brett", lastname = "guy", overlylongdescriptionfield = "omg have bunch of text denormalizing table putting bunch of stuff side related primary table." }, new person { personid = 2, firstname = "neil", lastname = "person"}, new person { personid = 3, firstname = "ryan", lastname = "other"}, new person { personid = 4, firstname = "aaron", lastname = "dude"}, }; foreach (var person in persons) context.person.addorupdate(person); } }
clearinghelper
public static void clearrange<t>(this dbset<t> dbset) t : class { using (var context = new easycontext()) { dbset.removerange(dbset); } }
okay issue newly created table being not populated , old table being populated. if have following off of example poco class 'person' , have plurilization removed. without explicit mapping , dbset create table person. if mapping split tables.
modelbuilder.entity<person>() .map(m => { m.properties(p => new { p.personid, p.firstname, p.lastname }); m.totable("person"); }) .map(m => { m.properties(p => new { p.personid, p.overlylongdescriptionfield }); m.totable("persondescription"); });
i primary key violation seeding process. due if @ database newly updated still retaining old table , created new one. not know how remove data method:
public static void clearrange<t>(this dbset<t> dbset) t : class { using (var context = new easycontext()) { dbset.removerange(dbset); } }
becase set partial. thinking: "well if data seeding contained @ point , need alter moving forward can in theory clean tables directly sql commands." not approach wanted per work.
so add more data clearing helper:
public static void resetidentity(string tablename) { using (var context = new easycontext()) { context.database.executesqlcommand($"dbcc checkident('{tablename}', reseed, 0)"); } } public static void deletetable(string tablename) { using (var context = new easycontext()) { context.database.executesqlcommand($"delete {tablename}"); } } public static void deletetableandresetidentity(string tablename) { using (var context = new easycontext()) { context.database.executesqlcommand($"delete {tablename}"); context.database.executesqlcommand($"dbcc checkident('{tablename}', reseed, 0)"); } }
then add seeding routine's cleanup portion:
clearinghelper.deletetable("dbo.persondescription"); clearinghelper.deletetableandresetidentity("dbo.person");
this unfortunate in 2 ways way in that:
- it slower doing delete goes row row.
- if migrate backwards have change this.
but works! can have changes schema normalizing out poco's , still run seeding routine.
Comments
Post a Comment