3

I have an MVC3 app which was using EF CTP5. After upgrading to EF 4.1 I get NullReferenceException thrown from here:

   at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase()
   at System.Data.Entity.Internal.InternalContext.Initialize()
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
   at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
   at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)

I've got EF 4.1 bits from NuGet.

Database is initialized using custom initializer

    public class RecreateDatabaseInitializer : IDatabaseInitializer<DatabaseContext>
    {
        public void InitializeDatabase(DatabaseContext context)
        {
            if (ConfigurationManager.ConnectionStrings["DatabaseContextSA"] == null)
            {
                EventLog.WriteEntry("RecreateDatabaseInitializer", "Connection string 'DatabaseContextSA' doesn't exist in config file.", EventLogEntryType.Warning);
                return;
            }

            using (var ctx = new DatabaseContext("DatabaseContextSA"))
            {
                if (ctx.Database.Exists())
                    DropDatabase(ctx);

                CreateDatabase(ctx);
                InitializeDatabaseObjects(ctx);
                ctx.SaveChanges();
            }

            PopulateDatabase(context);
            context.SaveChanges();
        }
    }

The Exception is thrown from PopulateDatabase() method.

Any ideas?

UPDATE:

It seems that the problem stems from the instantiation of the second DatabaseContext to manually recreate the database. It must somehow interfere with the original context.

Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • 1
    How do you initialize database? – Ladislav Mrnka Mar 19 '11 at 22:40
  • @Jakub, I don't see the `NullReferenceException` in the stack trace of the Exception... furthermore, can you replicate the error with a [sscce](http://www.sscce.org) compliant example? – Kiril Mar 19 '11 at 22:41
  • @Ladislav - thank you, I'll try to change the initializer and see what will happen. – Jakub Konecki Mar 19 '11 at 22:48
  • Btw. why do you use second context? – Ladislav Mrnka Mar 19 '11 at 23:39
  • @Ladislav - I'm using SQL Server 2008 and the build-in `DropCreateDatabaseInitializer<>` won't drop the database when it's in use. So I create a second context with SA credentials to close all connections to the database. Do you know of a way to make `DropCreateDatabaseInitializer<>` cope with db in use? – Jakub Konecki Mar 19 '11 at 23:43
  • Yes I described it here: http://stackoverflow.com/questions/5288996/database-in-use-error-with-entity-framework-4-code-first/5289296#5289296 – Ladislav Mrnka Mar 19 '11 at 23:46
  • That's what I'm doing ;-) I'll try your decorator pattern from the other question. Děkuji! – Jakub Konecki Mar 19 '11 at 23:50
  • @Ladislav - Could you please put a link to your decorator initializer as an answer? I want to accept it. – Jakub Konecki Mar 20 '11 at 16:52
  • 1
    I think you have found your own solution. Move it to answer and accept it. If my decorator helped you just upvote my linked answer. I usually don't like re-posting plain links to other questions without any added information as answers. – Ladislav Mrnka Mar 20 '11 at 16:58
  • The root cause of the exception does appear to be attempting to open a second DB context. After experiencing the issue myself following an upgrade to the 4.1 RC, I simply removed the code that created the second context and the Initializer code began working again. – Chris Staley Mar 22 '11 at 15:30

1 Answers1

1

I have used Ladislav's decorator for closing opened connections but I had to modify it a bit. This was required (I believe) as I use sql authentication and have two connection strings (one with elevated permissions and one with only read/write).

public class ForceDeleteInitializer : IDatabaseInitializer<DatabaseContext>
{
    private readonly IDatabaseInitializer<DatabaseContext> InnerInitializer;

    public ForceDeleteInitializer(IDatabaseInitializer<DatabaseContext> innerInitializer)
    {
        this.InnerInitializer = innerInitializer;
    }

    public void InitializeDatabase(DatabaseContext context)
    {
        using (var ctx = new DatabaseContext("DatabaseContextSA"))
        {
            Database.SetInitializer<DatabaseContext>(null);
            ctx.Database.ExecuteSqlCommand("ALTER DATABASE " + ctx.Database.Connection.Database + " SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
        }

        this.InnerInitializer.InitializeDatabase(context);

        Database.SetInitializer<DatabaseContext>(this);
    }
}
Community
  • 1
  • 1
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126