I'm trying to create a new database using the code first concept of Entity Framework. However when running the code the database isn't created (using the DropCreateDatabaseIfModelChanges
setting), though the code is running fine. I'm seeing the following exception when I try to get something from the database.
My project is setup using a separate DataAccess
layer with an generic service and repository construction. So all my entities, repository and also database context are in a separate project within the solution.
My global.asax
file contains the following piece of code.
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
This should initialise a new database if it isn't there, right?
My database context class looks like this;
namespace Website.DAL.Model
{
public class MyContext : DbContext
{
public IDbSet<Project> Projects { get; set; }
public IDbSet<Portfolio> Portfolios { get; set; }
/// <summary>
/// The constructor, we provide the connectionstring to be used to it's base class.
/// </summary>
public MyContext()
: base("MyConnectionString")
{
}
static MyContext()
{
try
{
Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// This method prevents the plurarization of table names
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
}
}
}
I've created this class following several tutorials and articles on the internet. It's all new to me, but as far as I can see everything seems correct so far. So now the two entities I'm using. They're called 'Project' and 'Portfolio'. They look like this;
public class Portfolio
{
[Key]
public Guid Id { get; set; }
public String Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool IsPublished { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
And
public class Project
{
[Key]
public Guid Id { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool IsPublished { get; set; }
public String Title { get; set; }
}
The database I'm using is running on an external server, it came with the hosting provider I'm using. I've got a SQL Server database up and running and the connection string to the database is in the web.config
of the website project. I've already tried removing the database and let the code recreate it, which unfortunately didn't work. Am I missing something obvious here? Or could it be a simple thing as access-rights to the server to create databases?
Note: When I run the Database-Update -Script
command to generate SQL code, it seems that the correct SQL statements to create all tables are created.
UPDATE 1: Okay, thanks to some comments I came a bit further. I've added two properties to my entities to force some changes and I've also created an custom initializer like this;
public class ForceDeleteInitializer : IDatabaseInitializer<MyContext>
{
private readonly IDatabaseInitializer<MyContext> _initializer = new DropCreateDatabaseIfModelChanges<MyContext>();
public ForceDeleteInitializer()
{
//_initializer = new ForceDeleteInitializer();
}
public void InitializeDatabase(MyContext context)
{
//This command is added to prevent open connections. See http://stackoverflow.com/questions/5288996/database-in-use-error-with-entity-framework-4-code-first
context.Database.ExecuteSqlCommand("ALTER DATABASE borloOntwikkel SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context);
}
}
I've also removed the initializer from the constructor of my context, so this mean i've remove this line of code;
Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
After that i've added these three lines to my Global.asax file;
Database.SetInitializer(new ForceDeleteInitializer());
MyContext c = new MyContext();
c.Database.Initialize(true);
When debugging i'm now getting this exception;
This gives me the following information:
- InnerException says: The provider didn't return a ProviderManifestToken
- InnerException in the InnerException says: "For this operation an connection to the masterdatabase is required. A connection can't be made width the 'master'-database because the original connection is opened and the references has been removed from the connection. Please provide a non-open connection"
After these action the database is inaccessible, so most likely deleted..
What can possibly be done about this? It's most likely that I can't access the master database because my hostingprovider won't give me the proper access right ofcourse.
Since no other solution came by I decided to change my approach.
I've first created the database myself and made sure the correct SQL user was configured and I had access.
Then I removed the initializer and the code from the Global.asax file. After that I ran the following command in the Package Manager Console (since the layered design I had to select the correct project in the console);
After the migrations where enabled and I made some last minute changes to my entities I ran the command below to scaffold an new migration;
After my migrations were created I ran the following command in the console and voila, the database was updated with my entities;
To be able to seed the database when running the migration i've overridden the Seed method in my Configuraton.cs class, which was created when enabling the migrations. The final code in this method is like this;
The disadvantage at the moment is that I have to manually migrate with (only) 2 commands in the package manager console. But the same time, the fact that this doesn't happen dynamically is also good because this prevents possibly inwanted changes to my database. Further everything works just perfect.
befor intialize it run following code to create your database:
context.Database.CreateIfNotExists();
+1 for the detailed question.
Check that your connection string is pointing at the correct database and add the authorization attributes like this to access your database:
So First Remove the Db Name from the constructor parameter on context class and provide Db_name on the connection string and then try to rebuild your solution and run the application it will create Database for you application.
For Example :
I am not passing the Db-Name on constructor parameter
and on the Connection string I am passing the Db-name like below.