Database migration using code first in mvc 4 - asp.net-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.

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!

How can I Seed data from a SQL file?

I have a database connected to a MVC 4 Project.
The Database is creating automatically from this code:
public class ContextInitializer : DropCreateDatabaseIfModelChanges<ContextModel>
{
protected override void Seed(ContextModel context)
{
base.Seed(context);
}
}
I saw that people Seed back the database after drop and recreate with this code:
System.Data.Entity.Database.SetInitializer(new CarStore.Models.SampleData.cs);
This works grate. But my question is:
1st. How can I seed data from a SQL file, i have that SampleData.sql, and how can I 'run' that file to insert back all the data.
and 2nd is there a way to make BackUp to latest version from your database data, before you DropAndCreateIfModelChanges ?
And then to seed that data back from that file ?
Thanks.
I GOT THE ANSWER :)
I finally manage to solve this problem.
Here is the code, maybe someone needs it !
var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
context.Database.ExecuteSqlCommand(File.ReadAllText(baseDirectory +
"\\IF YOU HAVE ANOTHER DIRECTOR INSIDE BASEDIR \\SQL" + "\\YOURFILENAME.sql"));
It works for me very good and fast.
It's optimized and readable.

Grails - Recreate database schema for integration test

Is there a convenient way to force Grails / Hibernate to recreate the database schema from an integration test?
If you add the following in DataSource.groovy an empty database will be created before the integration tests are run:
environments {
test {
dataSource {
dbCreate = "create"
}
}
}
By default each integration test executes within a transaction that is rolled-back at the end of the test, so unless you're not using this default behaviour there shouldn't be any need to programatically recreate the database.
Update
Based on your comment, it seems you really do want to recreate the schema before some integration tests. In that case, the only way I can think of, is to run
drop and recreate the schema
use grails schema-export to import a fresh schema
class MyIntegrationTest {
SessionFactory sessionFactory
/**
* Helper for executing SQL statements
* #param jdbcWork A closure that is passed an <tt>Sql</tt> object that is used to execute the JDBC statements
*/
private doJdbcWork(Closure jdbcWork) {
sessionFactory.currentSession.doWork(
new Work() {
#Override
void execute(Connection connection) throws SQLException {
// do not close this Sql instance ourselves
Sql sql = new Sql(connection)
jdbcWork(sql)
}
}
)
}
private recreateSchema() {
doJdbcWork {Sql sql ->
// use the sql object to drop the database and create a new blank database
// something like the following might work for MySQL
sql.execute("drop database my-schema")
sql.execute("create database my-schema")
}
// generate the DDL and import it
// there must be a better way to execute a grails command from within an
// integration test, but unfortunately I don't know what it is
'grails test schema-export export'.execute()
}
#Test
void myTestMethod() {
recreateSchema()
// now do the test
}
}
First and foremost, this code is completely untested, so treat with deep suspicion and low expectations. Secondly, you may need to change the default transational behaviour of integration tests (with #Transactional) in order for this to work.
This seems to work fine, but it's obviously very tightly coupled to H2 so it would have been nice if the Hibernate plugin had exposed an api to take care of this.
http://h2database.com/html/grammar.html#script
class SomethingTestingTransactionsSpec extends IntegrationSpec {
static transactional = false // Why I need this
SessionFactory sessionFactory // Injected by Spring
DataSource dataSource // Also injected
File schemaDump
Sql sql
void setup() {
sql = new Sql(dataSource)
schemaDump = File.createTempFile("test-database-dump", ".sql") // Java 7 API
sql.execute("script drop to ${schemaDump.absolutePath}")
}
void cleanup() {
sql.execute("runscript from ${schemaDump.absolutePath}")
sessionFactory.currentSession.clear()
schemaDump.delete()
}
// Spock tests ...
}
It should be trivial to extract this code into a bean registered only for test environments. That should clean up the test code a bit and improve efficiency by only having to dump the schema once.
Well, you have access to executing arbitrary sql via sessionFactory, so you could call a grails schema export at the beginning of your tests and then just re-import the schema into your DB when needed.
Alternatively, I wonder if calling database migration plugin externally will accomplish the same.
Or you can trick grails into thinking your domain class has changed and force a reload via https://github.com/grails/grails-core/blob/v2.1.1/grails-hibernate/src/main/groovy/org/codehaus/groovy/grails/plugins/orm/hibernate/HibernatePluginSupport.groovy#L340 ( don't ask me how )

How to save and then update same class instance during one request with NHibernate?

I'm relatively new to NHibernate and I've got a question about it.
I use this code snippet in my MVC project in Controller's method:
MyClass entity = new MyClass
{
Foo = "bar"
};
_myRepository.Save(entity);
....
entity.Foo = "bar2";
_myRepository.Save(entity);
The first time entity saved in database succesfully. But the second time not a single request doesnt go to database. My method save in repository just does:
public void Save(T entity)
{
_session.SaveOrUpdate(entity);
}
What should I do to be able to save and then update this entity during one request? If I add _session.Flush(); after saving entity to database it works, but I'm not sure, if it's the right thing to do.
Thanks
This is the expected behavior.
Changes are only saved on Flush
Flush may be called explicitly or implicitly (see 9.6. Flush)
When using an identity generator (not recommended), inserts are sent immediately, because that's the only way to return the ID.
you should be using transactions.
a couple of good sources: here and here.
also, summer of nHibernate is how I first started with nHibernate. it's a very good resource for learning the basics.