Permission to drop database with DropCrateDatabaseIfModelChanges<> - c#

I am building a MVC solution, but I am not able to modify my model without getting a database error.
My Initializer looks like this:
public class Initializer : DropCreateDatabaseIfModelChanges<DatabaseContext>
{
protected override void Seed(DatabaseContext context)
{
...
}
}
The error says:
An exception of type 'System.Data.SqlClient.SqlException' occurred in EntityFramework.dll but was not handled in user code
Additional information: Cannot drop the database 'hemabiobank', because it does not exist or you do not have permission.
How can I get permission to drop the database? Is it the server provider that has made me unable to to drop it?
Side question: How do I avoid loosing data when I modify the model?

Permission to drop the database could be from a number of things. One the ones I could thing of is that the permissions you're using to access the database do not allow you to drop a database. Are you able to login to the management studio with those permissions and drop a DB through SQL.
In terms of avoiding losing data when modifying the model, you are correct in thinking about the seed model, but you can also use database migrations:
I wrote the following on another question but it is useful here too:
Migrations provide a way to update tables/columns etc. without losing all of your existing infrastructure.
To be able to modify your code first DB using migrations you first need to enable them. To do this, in the NuGet package console simply type Enable-Migrations and press return. Once you have done this, You can make any sort of change to your classes, Dbsets, context etc. and then update them by typing add-migration (migration name here). When you have done this you'll notice a folder is created in your project called 'Migrations' or something similar. Within this you'll see some .cs files which represent the code that will be applied when you want to update the database. To physically update the database after you've added a migration you need to run the Update-Database command in the console. This will alter the database structure without losing everything you've already achieved.
The reason you give each migration a name is that you're able to swap between migrations, so you could go back to a specific change and undo further changes if you need to. This is why you'll find a separate .cs file for each migration you add in the Migrations folder, so it knows how to apply changes.
You'll also notice a migration history table created in your database, this also represents your changes and it records the state of the database at the point of that migration.

Related

ASP.NET Core MVC local database and model controller

I have created an ASP.NET Core web application using the MVC pattern (by following this tutorial) and connected it to a local database that is now populated with some data. I have two questions, if someone please help me understand and answer them:
1) My default connection string is set to the following:
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-MyAppName;Trusted_Connection=True;MultipleActiveResultSets=true"
}
Is it possible, only by changing the name and path in this connection string, to re-create the exact same database elsewhere with the data that is currently stored in it (for example, as backup)?
I have found the local database here:
C:\Users\my-name\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB
But when I try to copy the .mdf file to back up the database, I get an error that says the file is open and cannot be copied. What is it open in? How can I simply back the db file up?
2) After creating a custom controller, I noticed that all the provided properties of my Personmodel are used in the auto-generated code; e.g. in my case:
public async Task<IActionResult> Create([Bind("Birthday,ID,Username,EmailAddress")] PersonModel personModel)
I thought this would mean that if we change the code in the model class, we need to search for and effect the changes accordingly, but then I realized if I want to keep using auto-generated code, I have to do all the same steps as when I am generating it for the first time, and then when it asks if I want to replace the old code with new code, I choose yes.
Is there a better way of doing this, because this would overwrite my custom code every time and destroy the data stored in my local database. Particularly, when I store data in its local database, and then I decide to change a column name or add something, this would override everything...
How do I go about this situation?
Question 1
The .mdf and other files associated with the database will be in use by the SQL Server service. If you want to take a backup, use SQL Server Management Studio - right-click the database in the object explorer, select Tasks and then Backup. If you want to use the backup database then you need to restore it - again in the object explorer, right-click the "Databases" folder and select Restore Database and then browse to wherever you created the backup file.
Question 2 (updated 7th Sep)
When you change your model classes, you can use the add-migration command in the console to generate a new migration class containing the code to transform the database from its current structure to the new structure which matches the updated models. If the migration can cause data loss, then backup the database and restore the backup under a different name before running update-database, You can then create a script to transform the data from the backup into the new structure of the updated database.
Scaffolded components are a bit different to Entity Framework migrations. Migrations are truly auto-generated classes, and most of the time you wouldn't need to update (or even look at) the generated code. Think of scaffolded components as being more like a kind of template - it's a way of getting started with the classes, methods, markup etc that you're most likely to need, which is quicker than writing it all from scratch. It's not an alternative to writing code though, the intent is that once you've created the scaffolded code, you'll maintain it manually going forward. There is no way (that I know of) to automatically update scaffolded code to match a new model whilst retaining any edits you've made to it. You have two options
Re-scaffold the code and then apply your edits to it
Update the code manually to match the new model
All you can really do is weigh up the two options and decide which one is the least effort.

Entity Framework core getting error when rerunning the Update Migration

I am working on asp.net core and using EF. I have created database from scratch using EF. Now whenever there are changes in the database, adding new columns, or changing the type etc. Then I run the Update-datebase migration but I am getting an error for having tables and other object in database. Can someone help me what changes would I need to make in order to make the migration successful?
The compile error mentioned that the object already exists. Lets say if I have customer table that is already created in the database, when I run the script again after adding new object or modification, I am getting that error, this does make sense but what is the common practice to deal with the issue?
As described in Migrations Overview after you are evolving your models (adding properties, removing properties, editing them and etc...) you need to update your database schema, in order to do that, you are required to add a new migration.
This can be possible in the one of following ways:
via .NET CLI
dotnet ef migrations add NewMigrationName
via PowerShell
Add-Migration NewMigrationName
After adding a new migration you just need to sync the database by:
Update-Database

Do I need a migration for EF code first when the database does not exist in SQL Azure?

I have tried lots of variations of EF migration v6.0.1 (from no database, to empty databases to existing databases) and I have a particular problem with Azure DB instances not being able to correctly be created on first deploy using Octopus deploy.
There are a number of places where this could be going wrong, so I thought I would check some basics of EF Code First migration with you fine people if I may:
If I create a code-first model, and know that the database does not exist in the intended target database server on Azure. With the default of 'CreateDatabaseIfNotExists' approach and with AutomaticMigrations disabled;
If I then call 'migrate.exe' with the assembly containing my DbContext and migration Configuration will I get a new database created with the current state of the model? or will I get a new database with nothing in it? i.e. do I need to explicitly 'add-migration' for the initial state of the model?
I have read in the documentation that the database instance should be created automatically by the migration process, but no one states clearly (at least to me) that this newly created database will be generated with the current model without a formal 'initial state' migration created.
So the question is this: do I need an explicit migration model generated for migrate.exe to work from?
Through whatever means I try, I get a database but the application launches with the unfriendly message "Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations." Remembering that this is the same application library that just created the database in the first place (from scratch) I fail to understand how this has happened!
I did manually delete the target database a few times via SQL Server management studio, is this bad? Have I removed some vital user account that I need to recover?
Migrations and the Database Initializer CreateDatabaseIfNotExists are not the same.
Migrations uses the Database Initializer MigrateDatabaseToLatestVersion, which relies upon a special table in the database _MigrationsHistory.
By contrast, CreateDatabaseIfNotExists is one of the Database Initializers which relies upon the special database table EdmMetadata. It does exactly as it implies: Creates a database with tables matching the current state of the model, i.e. a table for each DbSet<T>, only when the database does not exist.
The specific error you have quoted here, Model compatibility cannot be checked because the database does not contain model metadata., occurs due to the existence of DbSet<T> objects which were added to the code base after the initial database creation, and do not exist in EdmMetadata.
There are 4 basic Database Initializers available, 3 of which are for use when migrations is not being used:
CreateDatabaseIfNotExists
DropCreateDatabaseWhenModelChanges
DropCreateDatabaseAlways
Also note, the 4th Initializer, MigrateDatabaseToLatestVersion, will allow you to use Migrations even if AutomaticMigrations is disabled; AutomaticMigrations serves a diffierent purpose, and does not interact with the Database Initializers directly.
If you intend to use Migrations, you should change the Database Initializer to MigrateDatabaseToLatestVersion and forget about the other 3. If, instead, you intend to not use Migrations, then the choice of Initializer is situational.
CreateDatabaseIfNotExists will be more appropriate when you are certain that your data model is not undergoing active change, and you only intend to be concerned with database creation on a new deployment. This Initializer will elp ensure that you do not have any issues with accidental deletion of a database or live data.
DropCreateDatabaseWhenModelChanges is most appropriate in development, when you are changing the model fairly often, and want to be able to verify these changes to the model. It would not be appropriate for a production server, as changes to the model could inadvertently cause the database to be recreated.
DropCreateDatabaseAlways is only appropriate in testing, where your database is created from scratch every time you run your tests.
Migrations differs from these 3 Database Initializers, in that it never drops the database, it instead uses Data Motion to execute a series of Create Table and Drop Table SQL calls.
You also can use Update-Database -Script -SourceMigration:0 in the Package Manager Console at any time, no matter which Database Initializer you are using, to generate a full SQL script that can be run against a server to recreate the database.
Firstly, many thanks to Claies who helped me get to the bottom of this problem. I have accepted his answer as correct as ultimately it was a combination of his response and a few additional bits of reading that got me to my solution.
In answer to the actual posts question 'Do I need a migration for EF code first when the database does not exist in SQL Azure?' the answer is yes you do if you have disabled automatic migrations. But there is a little more to be aware of:
The Azure aspects of this particular problem are actually irrelevant in my situation. My problem was two-fold:
The migration being generated was out of sync with respect to the target model. What do I mean? I mean, that I was generating the migration script from my local database which itself was not in sync with the local codebase which created a migration that was incorrect. This can be seen by comparing the first few lines of the Model text in the __MigrationHistory. This awareness was helped by referring to this helpful post which explains how it works.
And more embarrassingly (I'm sure we've all done it) is that my octopus deployment of the web site itself (using Octopack) somehow neglected to include the Web.Config file. From what I can tell, this may have occurred after I installed a transform extension to Visual Studio. Within my nuget package I can see that there is a web.config.transform file but not a web.config. Basically this meant that when the application started up, it had no configuration file to turn to, no connections string at all. But this resulted in the slightly misleading error
Model compatibility cannot be checked because the database does not
contain model metadata.
Whereas what it should have said was, there isn't a connection string you idiot.
Hopefully this helps people understand the process a little better after reading Claies answer and also that blog-post. First though, check you have a web.config file and that it has a connection string in it...

Create SQL View With Entity Framework 6 Code First

I am new to Entity Framework 6 Code First and am trying to perform what I thought would be a simple task. I want to create a SQL View and then have an Entity in my database context that I can use to query the view.
I have tried articles such as this but the key difference in my case is that the SQL View is not an existing view coming from another existing database.
I examined the proposition made in this article but it seems like overkill to me that I would need to create some extension methods to do something as simple as create a view/entity combo and use it in my database context.
Am I missing something? I know it would be much easier if I weren't using Code First but please keep in mind it's Code First and I am trying to create a view, not reuse one from an existing database.
Colin and Kevin, Thank you for the link to your answer on the other post and your concise answer. I have used several resources to finally create a queryable entity based on a new SQL view. Just in case anyone else is new to EF 6.0 Code First and is just getting their feet wet, I do have a few steps that will hopefully benefit others in the future.
It may seem obvious to more seasoned Entity Framework developers, but in order to execute the 'Migration' approach you need to disable automatic migrations and actually dive into the guts of the Code First Migrations inner workings. Since automatic migrations is turned on out of the box, I had already created a fairly complex database with seed scripts all relying on automatic migrations and rebuilding the database on every run of my application. This post helped me wipe my migrations history and get to square 1 with automatic migrations turned off (I went with the web.config approach in case you were wondering)
After I had cleared my migrations information, I deleted the mdf from within solution explorer. That guaranteed that I wouldn't run into any problems when running Update-Database (further down the list of steps).
In the Package Manger console, I then executed Add-Migration Initial to generate an "Initial" migration. The result of this was the editable Up and Down methods as described in Colin's answer. I then followed the steps in Colin's answer by commenting out the table create statement (Entity Framework tries to create a table but we really want to create a view and map it to the Entity) and inserting my own view create sql statement at the end of the Up method. It's important to put the create statement after the creation of any tables that it may depend on. I also performed my Seed activities in the Configuration.Seed method instead of in my Context's Seed method. I see how this would be important if you were dealing with multiple migrations. Finally, as Colin suggested I added the table mapping to my context's OnModelCreating event.
The final step in this was to actually apply the migration to the database. In order to do that, in the Package Manager console you execute the Update-Database command. That statement will rebuild the database with the "Initial" migration you created and edited in earlier steps.
It still surprises me that I need to do all of this custom work to create a view and map it to an entity with Code First, but at the end of the day it was helpful in getting me started on migrations as you can only rely on the "automatic migrations" for so long anyways.
You can manually add the sql to create the view to a migration then consume it as per your first link.
The answer in the link provided by Colin does the job.
In case there are lots of views to be created, it can be a good idea to save the view queries in separate files and add them in a resource (.resx) file instead of hard-coding the sql queries in the Migration Up() method.
For e.g.
public override void Up()
{
Sql("ResourceFileName.ResourceName");
}
instead of hard coding like
{
Sql("EXEC ('CREATE View [dbo].[ClientStatistics] AS --etc");
}

EntityFramework 6.0 CreateDatabaseIfNotExists Code first to create database

What am I doing wrong. I have got a user DbContext setup and working when I originally created the Code-First with powershell it all worked fine.
I implemented Database Initializer as expected on application start.
Database.SetInitializer<UserDbContext>(new CreateDatabaseIfNotExists<UserDbContext>());
Just to test out if it really creates the database I actually dropped the database and now I am stuck the database will not be created. I am using SQL Server 2012, any idea what could be wrong.
The error message I am getting is
System.InvalidOperationException: Migrations is enabled for context 'UserDbContext' but the database does not exist or contains no mapped tables. Use Migrations to create the database and its tables, for example by running the 'Update-Database' command from the Package Manager Console.
I have tried the same from Package Manager console and it is still give me the same message.
Finally figured the solutions, not sure why or what. Changed my Database initializer to MigrateDatabaseToLatestVersion instead of CreateDatabaseIfNotExists worked.
Database.SetInitializer<UserDbContext>(new MigrateDatabaseToLatestVersion<UserDbContext, Configuration>());
Edit:
With your new error message the problem comes from you having migrations enabled and already ran a migration (probably the first creation of the database) and since you dropped the DB the migration history has been lost. If your not using Automatic migrations you can not go in and make changes to the database your self and expect code-first to know about it. Try disabling migrations and re-enabling them to see if that clears out the migration history.
You will need to make a call into the DB either as a read or insert of data for the DB to initially be created. The code you use only tells EF how to deal with a database if one does not exist when it tries to find it. For me I use the method outlined at http://www.codeproject.com/Tips/411288/Ensure-Your-Code-First-DB-is-Always-Initialized

Categories

Resources