8

We're trying to figure out when exactly an Entity Framework Database Initializer runs.

MSDN says initializion happens the "first time" we access the database. When is "first time"?

MSDN contradicts itself, stating that initialization runs the first time an instance of a DbContext is used but also the first time a type of a DbContext is used. Which is it?

Further, MSDN doesn't define "first time"? Is this first time since publish? first time since Application_Start? first time for a given request, for a given method? What if we restart the application by changing the web.config?

Here are some quotes from MSDN, saying database initializer runs...

when an instance of a DBContext derived class is used for the first time

http://msdn.microsoft.com/en-us/library/gg696323%28v=vs.113%29.aspx

when the given DbContext type is used to access a database for the first time

http://msdn.microsoft.com/en-us/library/gg679461%28v=vs.113%29.aspx

For example, we have a controller action, in which we instantiate a DbContext and run an insert operation. If we call this action twice (or 10,000 times), will the DbInitializer run that many times? If we're using the DropDatabaseCreateAlways initializer, and we call this action twice, will the Db have two Event rows, or will the initializer delete the Db between inserts, thereby leaving one Event row?

public HttpResponseMessage PostEvent(EventDTO eventDTO)
{
    var ev = new Event()
    {
        Id = eventDTO.Id,
        Name = eventDTO.Name
    };

    using (AttendanceContext db = new AttendanceContext())
    {
        db.Events.Add(ev);
        db.SaveChanges();
    }

    return Ok();
}
Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
  • 4
    Pretty sure it's when you make your first read/update/delete/insert. – DavidG Oct 22 '14 at 15:17
  • Set up a packet sniffer around either your DB or your application and see for yourself exactly when it happens. – Servy Oct 22 '14 at 15:17
  • From my experience it when it is used to access a database for the first time. – Ben Robinson Oct 22 '14 at 15:17
  • It initialises when you first run the line db.context = (another context); it is the first time the database has been access ever so run the program an fierst time it does it second time you run it will NOT reinitailse – ZoomVirus Oct 22 '14 at 15:20
  • @DavidG Is it the first CRUD operation since Application_Start? I.e. what if we restart the application? Will the DbInitializer run another time? – Shaun Luttin Oct 22 '14 at 15:21
  • @Servy That's a good idea. Time and patience prohibit that right now. – Shaun Luttin Oct 22 '14 at 15:22
  • @Ben Do you mean the first time ever, the first time since Application_Start, the first time per request, or some other first time? – Shaun Luttin Oct 22 '14 at 15:23
  • 1
    It's not possible to find out by observing if you need to know for sure. You need to find docs or source code. – usr Oct 22 '14 at 15:34
  • 1
    @ShaunLuttin, I mean the first time it is used to access the database after it is instantiated. If you create a new instance, it will initialise it again, the first time you use that second instance. – Ben Robinson Oct 22 '14 at 15:36
  • 1
    So far, i have used `SQL Profiler` and found that when you do `db.Savechages` or select from some table, and used `.ToList()` , then it actually made SQL query to DB. – Arindam Nayak Oct 22 '14 at 15:36
  • @BenRobinson What does *it* refer to when you say the first time *it* is instantiated? Also, what is *first time* relative to? Is it the first time since Application_Start? – Shaun Luttin Oct 22 '14 at 15:39
  • Try this: Make the DB initializer call `WAITFOR DELAY '1:0:1' and pause the debugger while that runs. The calls stack tells you where in the source code to look. – usr Oct 22 '14 at 15:39
  • @ShaunLuttin, the DBContext – Ben Robinson Oct 22 '14 at 15:40
  • @BenRobinson I know that the initializer runs the first time that the `DbContext` is used. What I don't know is how to define "first time". Is it the first time per Request, the first time per application life cycle? – Shaun Luttin Oct 22 '14 at 15:42
  • 1
    @ShaunLuttin the first time a given instance connects to the server to execute some SQL. It is the first time within the lifetime of a given instance, so if you create 2 instances of the same context type they will both try initialise the databse. – Ben Robinson Oct 22 '14 at 15:49
  • @BenRobinson That's what I'm needing. Let's see whether I understand or not. If I have a controller action that runs `OurContext db = new OurContext()` and then runs a `db.SomeEntity.Select()` query, we're going to be initializing the database *every time* we call that controller action. Is that right? – Shaun Luttin Oct 22 '14 at 15:58
  • 2
    `.ToList()` (in this context) is the "First Time". – Brad Christie Oct 22 '14 at 15:59
  • 1
    @ShaunLuttin Yes that is correct, however it is not something I would be overly concerned about as if nothing needs to be done, whatever it does to check is very quick. – Ben Robinson Oct 22 '14 at 16:05
  • @BenRobinson That's good to know. What I'm more concerned about is keeping our data safe. If we're using `DropCreateDatabaseIfModelChanges` and the initializer runs every time an *instance* first accesses the Db, then we're going to be dropping our Db on schema changes, which would sometimes be a bad idea even during development. – Shaun Luttin Oct 22 '14 at 16:07
  • @BenRobinson I just ran the same controller action twice to test your comments. The results contradict your comment. The action instantiates a `DbContext`, then inserts a new record into the Db. The second time I ran the action, the insertion worked: we now have two records in the Db. That is, it did not recreate the database, even though we're using `DropDatabaseAlways`. What gives? – Shaun Luttin Oct 22 '14 at 16:32

1 Answers1

6

Entity Framework initializes the databse once per AppDomain startup.

When the DbContext class is first instantiated by your code, and one of it's properties are accessed, it uses an InternalContext instance that handles the initialization logic, and ensures that said initialization runs only once, using a static class field.

If you make a change on the web.config file, or when the application pool recycles or the iis process itself is restarted, your application domain will be started again and the initializer will fire. This post should help in knowing when this happens in web applications.

Reusing the same context instance multiple times, or even creating a new context on each request, will not trigger initialization each time.

Community
  • 1
  • 1
julealgon
  • 7,072
  • 3
  • 32
  • 77