Table of Contents

IT:AD:EF/CodeFirst:HowTo:Configure Seed

Summary

Once you've enabled Configure Migrations, you'll quickly come up to the issue of Seeding.

There are a couple of issues to get around first to make it easier to know what to do in various circumstances.

  • Seeding verus Data Updates
  • Where to put Data Updates (either Seeding, or Migrations)
  • When to use handy AddOrUpdate extension, or custom tests.

Process

Seeding Types

There are different forms of seeding that need to be considered:

The easiest way to handle that is something along the lines of:

var seedingType = _hostSettings.Get<SeedingType>("SeedingType");
if (seedingType >= SeedingType.ResetMutableReferenceData){
  dbContext.Categories.AddOrUpdate(x=>x.Name,new Category{Name="Default"});
}

In 99% of the cases, the seeding level should always be Seeding.ResetImmutableReferenceData.

But note that at that level that ensures you always have the necessary Reference Data – but doesn't take into account any new Mutable Records needed (AppSettings stored in the db would be a good example) or Mutable Records that need changing.

That's where Patches/Updates are needed.

Patches/Updates

Another form of data change to consider is Patches/Updates that change data.

Handling data updates requires more care.

A good example might be the updating of an AppSetting value (eg: FaxServerServiceEndpoint).

The reason this is more complex is:

So there are two places to consider putting it:

Each has Advantages and Disadvantages

In a Migration

* Advantages:

* Considerations:

* Disadvantages:

//Do migration:
   if ([]{"UAT","PP"...}.Contains (environmentIdentifier)){
     //do an update specific to a specific environment...
   }
   //or don't check environmentIdentifier, and do an update specific to all environments...

In Seeding

* Advantages:

* Considerations:

* Disadvantages:


if (!dbLog.Contains(x=>x.Name=="FooUpdate") && (!dbLog.Contains(x.Name=="FooUpdate")&&(x.Enabled==false)){
   if ([]{"UAT","PP"...}.Contains (environmentIdentifier)){
     //do an update specific to a specific environment...
   }
   //or don't check environmentIdentifier, and do an update specific to all environments...
}

AddOrUpdate versus Test/Insert

The easiest way to do seeding is to use the AddOrUpdate method:

studentCategories.AddOrUpdate(x=>x.Name, new StudentCategory("Asleep");

never test on the Id (x⇒x.Id), but a variable within the entity. If you test against the Id, and it's autoincremented, it doesn't ever work.

The downside is…AddOrUpdate is slow. Seeding used to happen only after applying a migration, but now it happens when ever you restart the app1). And by the time you've created a dozen or so reference tables…it's not fast.

In which case, consider testing whether you need to update things or not:

if (studentCategories.Count() <10){
  ...
  ...
  ...
}

Or you can also do

if (xactDataStoreUpdateLog.Contains(x=>x.Name=="BaseStudentCategories")){
  studentCategories.AddOrUpdate(x=>x.Name,....);
}
and if you later add more:

if (xactDataStoreUpdateLog.Contains(x=>x.Name=="MoreStudentCategories")){
  studentCategories.AddOrUpdate(x=>x.Name,....);
}

Instead of x queries, it's only x the first time, and then 1 the next time.

That said, you really have to stay on top of it to ensure you don't muck up and drop updates. Make it clear that nobody can update previously created sections – only create new sections 'MoreStudentCategoriesA…B…C…'…or use Migrations (see above).

Resources