Problems creating a database model with Entity Framework Code First - sql

I'm trying to create a database model with Code First, without creating the database itself. That is, my DBA has set up an empty database, for which I have permission to create tables, but not a whole database. However, whenever I try to use Code First to set up the model, I get the following error:
CREATE DATABASE permission denied in database 'master'.
Is this just the way Code First works, or is there some way to modify the existing database?
P.S. -- here's the connection string --
<add name="HoursDb"
connectionString="Data Source=barksql.cedarville.edu;
Initial Catalog=Hours;
persist security info=True;
User ID=hours;
password=************;
multipleactiveresultsets=True;
App=EntityFramework"
providerName="System.Data.SqlClient" />
Update
Per #devdigital's request --
Here is the context class:
using System.Data.Entity;
using ....Models;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace LibraryAdmin.DAL
{
public class HoursDb : DbContext
{
public DbSet<DaySpec> DaySpecs { get; set; }
public DbSet<WeekSpec> WeekSpecs { get; set; }
public DbSet<ExceptionHoursSet> ExceptionHoursSets { get; set; }
public DbSet<Schedule> Schedules { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
As far as mapping the database to the connection, I am assuming it is done by a convention since the HoursDb classname matches the connection string name.

It would seem that Entity Framework Code First deals with database model changes in two ways: one, it discards the old database and re-creates a new one; or two, it does not rest content until the user manually modifies it, as affirmed by #devdigital's link to EF 4.1 CF: CREATE DATABASE permission denied in database 'master'. Slauma's suggestion therein of using Database.SetInitializer(null); is good to ensure a production database is not dropped after creation, but does not create a table structure out of an empty database like I was trying to do. This being considered, my DBA granted me create access since he'd rather us not have to manually create every table, so it's not an issue anymore.
P.S. -- the database drop I mentioned came as a result of using one of the drop initialization strategies, probably DropCreateDatabaseAlways. Glad to know it was doing it's job.

Related

EntityFramework Core automatic migration

In my project I have 2 databases: one is my custom database and the other one is ApplicationDbContext that Microsoft Identity gives me.
In my Startup.cs I have this code:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ApplicationDbContext db, MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
db.Database.Migrate();
dbPSC.Database.EnsureCreated();
dbPSC.Database.Migrate();
}
I don't know when there is a migration to migrate, right? Then, I have 2 errors:
the migration for ApplicationDbContext raises an error every time the application starts apart from the first time
the migration for my context seems fine
What is the best practise to use? Is it necessary to call the migration for ApplicationDbContext?
Update
I have removed the Migration folder. Then, changed the Startup.cs like
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ApplicationDbContext db, MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
dbPSC.Database.EnsureCreated();
}
but when the application starts, it doesn't create any tables at all. AuditDbContext is because I use Audit.net
public class MyContext : AuditDbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options) { }
public DbSet<Message> Messages { get; set; }
public DbSet<AuditMessage> Audit_Messages { get; set; }
#region Common Tables
public DbSet<Country> Countries { get; set; }
public DbSet<AuditCountry> Audit_Countries { get; set; }
#endregion
#region Seed
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Seed();
}
#endregion
}
Update #2
I tried another solution but it doesn't work. The solution is to use RelationalDatabaseCreator like the following code
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ApplicationDbContext db, MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
dbPSC.Database.EnsureCreated();
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();
}
As the Migrate(), the first time the app runs it creates the tables but the second time it raises an error because the tables are already exist in the database.
The issue is most likely that you're calling EnsureCreated().
From the docs:
Note that this API does not use migrations to create the database. In addition, the database that is created cannot be later updated using migrations. If you are targeting a relational database and using migrations, you can use the DbContext.Database.Migrate() method to ensure the database is created and all migrations are applied.
So, it's enough to call Migrate(). But I don't blame you, because EnsureCreated() is definitely a misleading method name. It does a lot, since it also creates the DB schema that is not even based on migrations, but on the current state of the entities.
But if you don't want to use migrations for Identity context (because you don't extend those entities in any way), then the reverse is true: You don't need to call Migrate(), and calling EnsureCreated() is enough to make sure that the schema is created the first time.
Is calling Migrate() necessary?
As for what's best practice: Some developers don't like to call Migrate() at all from code, because they believe that DB schema operations like that should be more controlled (I'm sure you know that you can execute db update from CLI too). It depends on your requirements I guess.
And with respect to this specific case on having a separate database for Identity tables: They most likely will never change, and they especially won't create a migration by themselves. So I'd say that calling Migrate() on it is unnecessary, besides the fact that it can create and migrate the database if it didn't exist (so it might be useful to keep for that reason; if you're using migrations for that context to begin with).
Detecting whether migration is needed
You can use context.Database.GetPendingMigrationsAsync() to check if migration is needed. How it's done is that the DB has an EFMigrationsHistory table that stores the Id of the applied migrations, which can be compared to the migrations files in your solution.
But I think most developers don't call this GetPendingMigrationsAsync() (or the sync version, for that matter), because you can just call Migrate(), and if the DB is already updated, no harm is done.
Clarifying Migrations vs EnsureCreated
I'm not sure how much have you worked with EF, so chances are this is obvious. But Migrate() is used when you already created migrations with e.g. dotnet ef migrations add <migrationname>, which is a way to incrementally alter the database schema with a code-first approach.
But if you don't use migrations at all, you have a very simple schema that won't be needed to be altered incrementally with migrations, and you just want to make sure that the DB exists with a schema, then use only EnsureCreated(), and don't use Migrate().
The issue is that if you happen to change your entities, EnsureCreated() won't update the database; if the database already exists, it does nothing. So you'd have to call EnsureDeleted() followed by EnsureCreated() to achieve an up-to-date DB schema without migrations. Which obviously involves losing all your data. This is why migrations are useful. EnsureCreated() is mostly used for e.g. integration testing.
Btw, you can use the same DB context for your own tables and Identity; I'd hazard to say that's the 'normal' way of working with EF. Of course you could have your specific reasons for separating I suppose.
You don't need to use both db.Database.EnsureCreated(); and db.Database.Migrate();
You need to use db.Database.EnsureCreated(); when you don't have migrations enabled in your application. If you have migrations enabled then only use db.Database.Migrate(); and that would be enough.
But if you don't enable migrations then on every change you have to re create your db. Because "EnsureCreated" only verifies if the db already exists. So better to enable Migrations.
So if you don't want to change anything in ApplicationDbContext so you can use db.Database.EnsureCreated(); but if you want to change something or may be you want to add more fields in AspNetUsers etc then you should enable migrations and use db.Database.Migrate();
Btw you can also add your custom tables in ApplicationDbContext if you want.
Based on the replies you guys sent to me, my solution is to use migration. In the Startup.cs I added those lines of code (dbPSC is a DbContext)
dbPSC.Database.EnsureCreated();
if (dbPSC.Database.GetPendingMigrations().Count() > 0)
dbPSC.Database.Migrate();

NuGet Update-Database is not pulling new records in Visual Studio

Novice to VisualStudio and NuGet so I'm looking for some instruction.
I'm on a team project using TFS and using NuGet to get updates for the database of this project.
One of my team members added in a property, that added a column to one of our databases, and then also added a new record to that database. Then he created a new migration for that instance.
I am trying to update this into the rest of our VisualStudio setups.
From my research so far, I ran the command Update-Database in the NuGet package manager. This updated the structure of the database and brought in the new column but failed to bring in the new record.
We have tried Update-Database -force and that came back with nothing.
I've tried searching for a solution but I'm having a hard time finding information on migrating data in the database.
Does anyone have any suggestions on how I can go about this easily for many future updates.
Firstly, welcome to SO!
This updated the structure of the database and
brought in the new column but failed to bring in the new record.
When you create a migration, EF will automatically add the structural changes but it doesn't do the same for data. Which, if you think about it, makes sense as EF has no way of knowing what records have been added, amended or removed in your database and 9 times out of 10 we wouldn't want that data being in a migration script.
If you want to include records with your migration you have two options...
1. Seed The Database
This method will be called upon each migration
internal sealed class Configuration : DbMigrationsConfiguration<WebApplication15.DatabaseContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(WebApplication15.DatabaseContext context)
{
//
// Add records into the database
//
}
}
2. Add Data to the Migration
public partial class Initial : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.People",
c => new
{
Id = c.Int(nullable: false, identity: true),
})
.PrimaryKey(t => t.Id);
Sql("INSERT INTO People....");
}
public override void Down()
{
DropTable("dbo.People");
}
}
We have tried Update-Database -force and that came back with nothing.
The force flag just tells EF to migrate the database regardless of whether or not it might result in data loss (i.e dropping a table that is full of records!).
Hope this helps!

Database migration using code first in mvc 4

I have created my mvc 4 application using code first and accordingly database and table also generated now i want to delete one column (from backend) of my table. so i just want to know is there any way so that changes can occur in my code automatically according to change in database.
through package manager console using migration technique
PM> enable-migrations -EnableAutomaticMigrations
in code configuration do the following
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
now when model changes do the following.
PM> update-database
Doing it through code
Use DropCreateDatabaseAlways initializer for your database. It will always recreate database during first usage of context in app domain:
Database.SetInitializer(new DropCreateDatabaseAlways<YourContextName>());
Actually if you want to seed your database, then create your own initializer, which will be inherited from DropCreateDatabaseAlways:
public class MyInitializer : DropCreateDatabaseAlways<YourContextName>
{
protected override void Seed(MagnateContext context)
{
// seed database here
}
}
And set it before first usage of context
Database.SetInitializer(new MyInitializer());
Well if you are using code first technique then remove column from your model and run migration script(google it) this will remove column from your database. But what you want is reverse which I am not sure could be done or not.

Database in use error with Entity Framework 4 Code First

I have an MVC3 and EF 4 Code First application, which is configured to change the DB when the model changes, by setting the DB Initializer to a DropCreateDatabaseIfModelChanges<TocratesDb>, where TocratesDb is my derived DbContext.
I have now made a change to the model, by adding properties to a class, but when EF tries to drop and recreate the DB, I get the following error:
Cannot drop database "Tocrates" because it is currently in use.
I have absolutely no other connections anywhere open on this database. I assume that my cDbContext still has an open connection to the database, but what can I do about this?
NEW: Now my problem is how to re-create the database based on the model. By using the more general IDatabaseInitializer, I lose that and have to implement it myself.
Your current context must have an opened connection to be able to drop the database. The problem is that there can be other opened connections which will block your db initializer. One very nice example is having opened any table from your database in management studio. Another possible problem can be opened connections in the connection pool of your application.
In MS SQL this can be avoided for example by switching DB to SINGLE USER mode and forcing all connections to be closed and incomplete transactions rolled back:
ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE
You can create a new intializer which will first call this command and then drops the database. Be aware that you should handle a database connection by yourselves because ALTER DATABASE and DROP DATABASE must be called on the same connection.
Edit:
Here you have example using Decorator pattern. You can modify it and initialize inner initializer inside the constructor instead of passing it as a parameter.
public class ForceDeleteInitializer : IDatabaseInitializer<Context>
{
private readonly IDatabaseInitializer<Context> _initializer;
public ForceDeleteInitializer(IDatabaseInitializer<Context> innerInitializer)
{
_initializer = innerInitializer;
}
public void InitializeDatabase(Context context)
{
context.Database.SqlCommand("ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context);
}
}
I found in EF 6 this fails with an ALTER DATABASE statement not allowed within multi-statement transaction error.
The solution was to use the new transaction behavior overload like this:
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "ALTER DATABASE [" + context.Database.Connection.Database + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
I had the same issue.
I resolved it by closing a connection open under the Server Explorer view of Visual Studio.
I realize this is dated but I couldn't get the accepted solution working so I rolled a quick solution...
using System;
using System.Data.Entity;
namespace YourCompany.EntityFramework
{
public class DropDatabaseInitializer<T> : IDatabaseInitializer<T> where T : DbContext, new()
{
public DropDatabaseInitializer(Action<T> seed = null)
{
Seed = seed ?? delegate {};
}
public Action<T> Seed { get; set; }
public void InitializeDatabase(T context)
{
if (context.Database.Exists())
{
context.Database.ExecuteSqlCommand("ALTER DATABASE [" + context.Database.Connection.Database + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
context.Database.ExecuteSqlCommand("USE master DROP DATABASE [" + context.Database.Connection.Database + "]");
}
context.Database.Create();
Seed(context);
}
}
}
This works for me and supports seeding easily.
In Visual Studio 2012, the SQL Server Object Explorer window can hold a connection to the database. Closing the window and all windows opened from it releases the connection.
A simple closing of my whole project and reopening it did the trick for me. It's the easiest way to make sure there are no connections still open

SessionFactory - one factory for multiple databases

We have a situation where we have multiple databases with identical schema, but different data in each. We're creating a single session factory to handle this.
The problem is that we don't know which database we'll connect to until runtime, when we can provide that. But on startup to get the factory build, we need to connect to a database with that schema. We currently do this by creating the schema in an known location and using that, but we'd like to remove that requirement.
I haven't been able to find a way to create the session factory without specifying a connection. We don't expect to be able to use the OpenSession method with no parameters, and that's ok.
Any ideas?
Thanks
Andy
Either implement your own IConnectionProvider or pass your own connection to ISessionFactory.OpenSession(IDbConnection) (but read the method's comments about connection tracking)
The solution we came up with was to create a class which manages this for us. The class can use some information in the method call to do some routing logic to figure out where the database is, and then call OpenSession passing the connection string.
You could also use the great NuGet package from brady gaster for this. I made my own implementation from his NHQS package and it works very well.
You can find it here:
http://www.bradygaster.com/Tags/nhqs
good luck!
Came across this and thought Id add my solution for future readers which is basically what Mauricio Scheffer has suggested which encapsulates the 'switching' of CS and provides single point of management (I like this better than having to pass into each session call, less to 'miss' and go wrong).
I obtain the connecitonstring during authentication of the client and set on the context then, using the following IConnectinProvider implementation, set that value for the CS whenever a session is opened:
/// <summary>
/// Provides ability to switch connection strings of an NHibernate Session Factory (use same factory for multiple, dynamically specified, database connections)
/// </summary>
public class DynamicDriverConnectionProvider : DriverConnectionProvider, IConnectionProvider
{
protected override string ConnectionString
{
get
{
var cxnObj = IsWebContext ?
HttpContext.Current.Items["RequestConnectionString"]:
System.Runtime.Remoting.Messaging.CallContext.GetData("RequestConnectionString");
if (cxnObj != null)
return cxnObj.ToString();
//catch on app startup when there is not request connection string yet set
return base.ConnectionString;
}
}
private static bool IsWebContext
{
get { return (HttpContext.Current != null); }
}
}
Then wire it in during NHConfig:
var configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.Provider<DynamicDriverConnectionProvider>() //Like so