1

New to MVC.

I seem to be stuck in a bit of a Catch-21 (not quite as severe as a Catch-22).

To keep unnecessary database traffic down, I'd like to call my method to populate the initial Identity data (create admin user, admin role, etc.) only when the database is first created (e.g. during CreateDatabaseIfNotExists(Of ApplicationDbContext)).

The trouble stems from the fact that my Startup config must set the DbContext first, before ApplicationUserManager and ApplicationSignInManager are set:

Builder.CreatePerOwinContext(AddressOf ApplicationDbContext.Create)
Builder.CreatePerOwinContext(Of ApplicationUserManager)(AddressOf ApplicationUserManager.Create)
Builder.CreatePerOwinContext(Of ApplicationSignInManager)(AddressOf ApplicationSignInManager.Create)

The ApplicationUserManager.Create() method calls ApplicationDbContext, so the calls have to be in that order.

Here's the relevant bit of my Identity initialization code:

Public Shared Sub InitializeIdentity()
  Dim oUserManager As ApplicationUserManager
  Dim oRoleManager As ApplicationRoleManager

  oUserManager = HttpContext.Current.GetOwinContext.GetUserManager(Of ApplicationUserManager)
  oRoleManager = HttpContext.Current.GetOwinContext.Get(Of ApplicationRoleManager)

  ...

End Sub

See the problem? ApplicationUserManager relies on ApplicationDbContext and ApplicationDbContext relies on ApplicationUserManager (the latter only when I try to run InitializeIdentity() from the overridden Migrations.Configuration.Seed() method).

Sure, I could put the InitializeIdentity() call elsewhere in my startup, but then it'd run on every single page load when it only needs to run once when the database is first created. That's a huge amount of completely unnecessary hits to the database.

Is there a way to escape this logic loop? How can I tell the framework to run the Identity initialization after ApplicationUserManager is set—only once, upon database creation—when the context has to be set first?

InteXX
  • 6,135
  • 6
  • 43
  • 80
  • Initializers also have a seed that is only called on database creation. See here: https://stackoverflow.com/questions/29526215/seed-entities-and-users-roles/29547994#29547994 – Steve Greene Sep 23 '20 at 03:16
  • For some odd reason, the `Seed()` method is never called when using that construct, at least not in my code. In fact I'd tried that approach earlier and abandoned it for this very reason. Do have any guess as to why `Seed()` isn't running? – InteXX Sep 23 '20 at 03:44
  • It won't run if the database exists. Delete the database or use a different initializer like [DropCreateDatabaseIfModelChanges](https://www.entityframeworktutorial.net/code-first/database-initialization-strategy-in-code-first.aspx). – Steve Greene Sep 23 '20 at 22:19
  • Pardon me, I failed to mention that. I'm manually deleting the database on each test run. The seed method is never called. I'm finding other discussions that seem to indicate this as a bug in EF. So if your version is working I'm surprised. – InteXX Sep 23 '20 at 22:38
  • Your answer [here](https://stackoverflow.com/a/29547994) turned out to provide the solution for me. Until I saw that, I wasn't aware of how to instantiate `UserManager` and `RoleManager` as completely new objects, instead of attempting to get them from the OWIN context (where they didn't exist yet). If you'd like to make this into an answer here, I'd be pleased to accept it. – InteXX Sep 28 '20 at 17:54

0 Answers0