.NET Core database model changes in production - asp.net-core

I follow code first approach to generate my databases by EFCore.
Now during development one of my models changed. How can I update the corresponding database tables on a live system at one of our customers? I do not want to dump or delete any data of course.
I'm still on .NET Core 1.1.0.

I fear you'll have to swallow the pill then.
Database.EnsureCreated() is only useful for developing, where you don't have to preserve data. If you have to preserve data or change the table schema, you have to use migrations or database scaffolding (create models from Database schema).
In any case, do a backup of the production data, before applying/attempting following steps and try it out upfront on a staging server.
One touchy option would be...
restore your code (i.e. going back to an older revision in your VCS)
create a table layout based on it (running Add-Migration InitialVersion or dotnet ef migrations add InitialVersion followed by Update-Database or dotnet ef database update
reapply your model changes (going back to your current revision in VCS, but keeping the files in the Migration folder)
run Add-Migration ModelUpdateV2 or dotnet ef migrations add ModelUpdateV2
run Script-Migration (Thanks #Smit!) or dotnet ef migrations script. This will generate an SQL command for applying the changes to the schema
From now on you have two options:
Look for a __EFMigrationHistory table within your database on the development database. It should contain one entry with your initial migration name. Export this table into your production system. Then you application should apply the migrations on the next start (when you call context.Database.MigrateAsync() within your Startup.cs).
From now on you should be able to use migrations in future
Just execute the migration script from above, without copying over __EFMigrationHistory, but then you'll have to repeat the steps above.
The other option is, to always create the models from the database (see dotnet ef dbcontext scaffold command (see EF Core Docs) do create models from database schema in future.
Then every time you change the table, you have to create your own SQL for migration and apply that before or while deploying the application.

Related

.NET Core Entity Framework: updating C# code for existing database for tables and other objects

I use ASP.NET Core 6 and use Entity Framework with an existing database.
Since my database already exists, I need to do reverse engineer to generate the code based on the existing database. I have seen some tutorials which show how I can do it. But what I see is, I am only able to get the tables but not other objects like, stored procedure, views, functions or triggers.
I have two questions:
When working with the database first approach where the database already exists in EF Core, when reverse engineering do I have to generate code for the other objects like I mentioned above, stored procedures, views and other?
Is it optional or must I have them?
If they are required how can I generate them in C# code?
You can only generate models from existing database using this command -
DOTNET CLI:
dotnet ef DBContext scaffold "Server=.;Database=db_name;User Id=user_id;Password=password" Microsoft.EntityFrameworkCore.SqlServer -o Models
PACKAGE MANAGER CONSOLE:
Scaffold-DbContext "Server=.;Database=db_name;Trusted_Connection=True;Id=user_id;Password=password" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
This command will reverse engineer db tables to models.

Alter table script in SQL Server database project

My Requirement is to create delta scripts for an existing project, so we will be making lot of changes and create more tables in it.
We have Dev, QA, Stage and Production environments. I want to do the changes only in dev environment and rest of the environments have to be taken care by Dacpac automatically using VSTS. All the scripts have to be re-runnable except the seed data.
I am able to add a table, but unable to add an alter table statement in database project in build mode. I don't want to import full database. Can the Dacpac not accept alter statements?
Since I have to check if exists for post deployment script, I don't want use alter statement there. How can I achieve this?
I think you may have miss understood what the SQL Server database project is/does. The project it self uses SQL scripts to build an in memory model of what your database looks like. This model then compiles down to a DACPAC which contains meta data that describes what the database should look like. When you deploy the DACPAC, this generates a change script that will transform the database into a state that matches the model described in the DACPAC.
The reason your ALTER TABLE doesn't work is due to there being no table to alter. The project isn't a database and it doesn't know how to represent in memory your ALTER statements. If you include it in a pre or post deploy script, the model will ignore this. It will, as you found out, mess with the deployments to the other environments.
The ideal way to deploy your database to your dev environment is using VSTS via CI/CD practices with the DACPAC. I'm not sure why you don't want to use a DACPAC to deploy to your dev environment, but if this is a hard fast rule, then you can use schema compare in Visual Studio's SSDT to copy your changes locally to the target database.

Entity Framework migrations looking for deleted table

I am using EF6.
I created a migration which had some issues, because SQL had created a index that it knew nothing about. Trying to manually fix up what EF migrations had generated created more problems than it solved, so I decided to delete the entire table in SQL, then re-scaffold the migration.
The problem is that the new migration expects the table to be there. I expected migrations to know that it wasn't there, but this is obviously not how it works? Is that correct?
Is there a way to tell Migrations to look at the current DB and re scaffold from there?
Thanks
Depending on where you are in development, the easiest thing might be to just delete existing migrations and apply a new baseline using the -IgnoreChanges attribute (https://msdn.microsoft.com/en-us/data/dn579398.aspx#option1).
Otherwise, you can go through the generated Up() code and comment out lines that don't need to be applied. Then do Update-Database and your model will be back in sync.

Running Azure Mobile Server project locally

I'm running an Azure Mobile Server project locally with a local SQL Database.
I started from the Quickstart project, but as soon as I change the Entity to something more complex, I get this error with my migration:
"Cannot create more than one clustered index on table..."
Even with the correct schema I get this other error:
"Automatic migrations that affect the location of the migrations history system table (such as default schema changes) are not supported. Please use code-based migrations for operations that affect the location of the migrations history system table."
If you're using migrations, there's a chance that EF is trying to create both the primary key and CreatedAt column as clustered indexes. If you tell the migration to use the Azure Mobile Services/Apps SqlGenerator, it should do the right thing.
See if my answer here fixes the issue for you.
This is an artifact of Entity Framework, the ORM that .NET Mobile Services use. It's recommended that you use Code First Migrations to address this issue. Mobile Services has a full guide which is kept up to date on how to enable code first migrations. https://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-how-to-use-code-first-migrations/
If you'd rather not deal with Code First Migrations, you can drop your database each time (not really a good idea for production purposes) or use the JavaScript backend.

Best Practices of continuous Integration with SQL Server project or local mdf file in project

Today I maintain project that has really messy DB that need a lot of refactor and publish on clients machines.
I know that I could add a SQL Server Database project that contains just scripts of the database and creates a .dacpac file that allows me to change clients databases automatically.
Also I know that I could just add an .mdf file to the App_Data or even to Solution_Data folder and have my database there. I suppose that localDb that already exists allows me to startup my solution without SQL Server
And atlast i know that Entity Framework exist with it's own migrations. But i don't want to use it, besouse i can't add and change indexes with it's migrations and i don't have anought flexibility when i need to describe difficult migrations scenarios.
My goals:
Generate migration scripts to clients DB's automaticaly.
Make my solution self-contained, that any new Programmer that came to project don't even need to install SQL Server on his machine.
Be able to update local (development) base in 1-2 clicks.
Be able to move back in history of db changes (I have TFS server)
Be able to have clean (only with dictionaries or lookup tables) db in solution with up to date DB scheme.
Additionally i want to be able to update my DB model (EF or .dbml) automatically or very easy way.
So what I what to ask:
What's a strengths and weaknesses of using this 2 approaches if I want to achive my goals?
Can be that I should use sort of combination of this tools?
Or don't I know about other existing tool from MS?
Is there a way to update my DAL model from this DB?
What's a strengths and weaknesses of using this 2 approaches if I want to achive my goals?
Using a database project allows you to version control all of the database objects. You can publish to various database instances and roll out changes incrementally, rather than having to drop and recreate the database, thus preserving data. These changes can be in the form of a dacpac, a SQL script, or done right through the VS interface. You gain a lot of control over deployments using pre- and post-deployment scripts and publishing profiles. Developers will be required to install SQL Server (the developer/express edition is usually good enough).
LocalDB is a little easier to work with -- you can make your changes directly in the database without having to publish. LocalDB doesn't have a built-in publish process for pushing changes to other instances. No SQL Server installation required.
Use a database project if you need version control for your database objects, if you have multiple users concurrently making changes, or if you have multiple applications that use the same database. Use LocalDB if none of those conditions apply or for small apps that require their own standalone database.
Can be that I should use sort of combination of this tools?
Yes. According to Kevin's comment below, "If the Database Project is set as your startup project, hitting F5 will automatically deploy it to LocalDB. You don't even need a publish profile in this case."
Or don't I know about other existing tool from MS?
Entity Framework's Code First approach comes close.
Is there a way to update my DAL model from this DB?
Entity Framework's POCO generator works well unless you make changes to your DAL classes, then those changes get lost the next time you run the generator.
There is a new tool called SqlSharpener which can generate classes from the SQL files in a database project. I have not used it so I cannot vouch for it but it looks promising.
One way for generating client script for DB changes is to use database modeling tool like ERWin Which have a free community edition. The best way to meet your database version control requirement and easy script generation is Redgate SQL Source Control. Using Redgate tool you will meet the first five goals mentioned. Moreover, you can now update EF Model by single click after changing DB schema (i.e. Database first approach) as required in goal 6.
I do not recommend using LocalDB at all. It always make issues with source control like "DB File is in use and can't commit...” In addition, the developer in the project will not have common set of updated data to work on unless a developer add test data to the database and ask others to get latest version and overwrite their own database Or generate update script by the previous mentioned tool and ask every developer to run it on his localDB.
The best way in your situation is to use SQL Server on network. A master version that all the developers use. Since you have version control on the database using previously mentioned tool, you can rollback any buggy change in the database server.
If you think that RedGate tool is expensive for the budget of your project. A second approach is to generate single SQL file from your database that has all database object and the other developers update the SQL file in source control per their changes. This can be done easily by using schema compare tool in visual studio and appending the generated script to SQL file in the source control. With EF DB First approach, you will not have to add many migration classes as in EF Code first.