I had created my project and configured the user entities.
I had enabled migrations in my project. To test this I simple added a user and then logged into the ASP NET application through the browser. It all worked great.
I added a couple more entities and their corresponding DbSet<T>. I created a controller to manage these entities.
I went to Update-Database using this seed method:
var manager = new UserManager<ChevieUser>(new UserStore<ChevieUser>(new DefaultContext()));
var people = new List<ChevieUser>
{
new ChevieUser { FirstName = "blah", LastName = "blah", UserName="cliningt", Email="blah.blah#blah.co.uk" }
};
people.ForEach(x => manager.Create(x, "password"));
context.SaveChanges();
var projects = new List<Project>
{
new Project { Name= "MLounge", ProposedDuration = DateTime.Now.AddDays(14), Users = new List<ChevieUser>(){context.Users.FirstOrDefault()} }
};
projects.ForEach(x => context.Projects.AddOrUpdate(p => p.Name, x));
context.SaveChanges();
//var targets = new List<Target>
//{
// new Target {Name="Initial Meeting", CompletionDate = DateTime.Now.AddDays(1), ProjectId = context.Projects.FirstOrDefault().Id},
// new Target {Name="Pricing", CompletionDate = DateTime.Now.AddDays(2), ProjectId = context.Projects.FirstOrDefault().Id},
// new Target {Name="Layout", CompletionDate = DateTime.Now.AddDays(3), ProjectId = context.Projects.FirstOrDefault().Id}
//};
//targets.ForEach(x => context.Targets.AddOrUpdate(p => p.Name, x));
//context.SaveChanges();
It created a project, however, the project had an Id of a empty Guid. Even though I am using the same code to for the Id property as I have done with every other project.
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
The reason why the targets code is commented out is that it can't add three targets with the same Id because the above code isn't working properly.
So I thought I would update my MVC project with the latest nuget packages. This was successful. However, when I came to Update-Database there was an error that migrations was not enabled in my project!
Then after trying to Enable-Migrations it came back with an error that there is no context!
From everything working perfectly fine, to the whole project messing up like this is so bizarre. Out shot of it is, migrations seems to have magically disable itself, but even when it was working, the DatabaseGenerated(DatabaseGeneratedOption.Identity) wasn't working properly.
It sounds like EF is looking in the wrong project.
Make sure the "Default Project" dropdown in your Package Manager Console window is set to the project that contains your DbContext class. This tells the package manager console which project to execute commands against.
Related
I have Entity Framework (6.1.1) set up with migrations. I know I can run the following command in the Package Manager Console to reset the database to be completely empty:
Update-Database –TargetMigration: $InitialDatabase
But how can I do this from my code?
var configuration = new MyDbConfiguration();
configuration.TargetDatabase = new DbConnectionInfo(
"Server=MyServer;Database=MyDatabase;Trusted_Connection=True;",
"System.Data.SqlClient");
var migrator = new DbMigrator(configuration);
migrator.Update("201606030938116_InitialDatabase");
if you do not know your migration Id then you can just do:
migrator.GetDatabaseMigrations().First();
or:
migrator.GetLocalMigrations().First();
In your DbConfiguration you have to allow the auto dropping:
public class MyDbConfiguration: DbMigrationsConfiguration<MyDbContext>
{
public MyDbConfiguration()
{
this.AutomaticMigrationsEnabled = true;
this.AutomaticMigrationDataLossAllowed = true;
}
}
Update from #GTHvidsten:
Instead of getting the available migrations, you have to use this command: migrator.Update(DbMigrator.InitialDatabase);. But you also have to set the ContextKey property in MyDbConfiguration to match the one used in the Configuration object created by Package Manager. With both of these my database becomes empty.
I'm refactoring a project and want to move all the EF entities and the code-first migrations to a new project. I renamed the ContextKey in the _Migrations table to the new namespace. When running an Add-Migration, no new changes are detected (Up() and Down() are empty).
But when I remove the localdb, the db isn't re-created (it did before the move). Apparently only migrations created after the move are run (but it shouldn't).
How can I make sure all migrations (also the ones before the move) are run when creating a new db?
--edit--
Never mind :(
I dragged and dropped the existing migrations to the new project and renamed the namespaces in the migration.cs files, but forgot the code behind migration.Designer.cs
You can update all the ContextKey column values in the dbo._MigrationHistory table to match the new namespace and that's all.
For me i was moving all the code first models from ASP.NET MVC app to external Class library to share with other projects.
Below steps may help
check the dbo._MigrationHistory and you can see all records have
similar values which match the exact class of Configuration class
MyApp.Migrations.Configuration
2.(test step) run Update-Database from Package Manager Console with new class library selected and you will see for example below error
There is already an object named 'AspNetRoles' in the database.
update all the records in the ContextKey column of _MigrationHistory table to match the new namespace
MyApp.Domain.Migrations.Configuration
The reference table [__MigrationHistory] contains a ContextKey column. Unless otherwise valued, it maintains the value of the membership of DbContext namespace.
You can set a class that derives from dbMigrationsConfiguration and set the ContextKey value in the constructor.
public sealed class Configuration : DbMigrationsConfiguration<Your.Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
ContextKey = "PreviousValue";
}
protected override void Seed(Your.Context context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
I am building an MVC 5 website with code first migration approach. Also, mention that I'm using Visual Studio Online linking to my Azure Web site. So, when I use Team Explorer in VS 2013 to do a check in, it automatically is deployed to Azure web sites.
Locally all works OK. However, when deploying it to Azure (check in) the following points are NOT performed:
If a new table is created using the code first approach, it is not created when deploying to Azure
The seed method (in the configuration.cs file) is not executed.
Due to the above, I have to manually either create the new tables or adding the test data. Google it for a solution I have read that this is a problem in the .Net framework due to the kind of index (nonclustered) to is set by default.
So, I have trying to use different alternatives. As for example:
public Configuration()
{
AutomaticMigrationsEnabled = true;
ContextKey = "MySolution.Models.ApplicationDbContext";
SetSqlGenerator("System.Data.SqlClient", new AzureSqlGenerator());
}
Where I created the AzureSqlGenerator class:
public class AzureSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(CreateTableOperation createTableOperation)
{
if ((createTableOperation.PrimaryKey != null)
&& !createTableOperation.PrimaryKey.IsClustered)
{
createTableOperation.PrimaryKey.IsClustered = true;
}
base.Generate(createTableOperation);
}
}
But, that doesn't work.
Long story short, I have the following two questions:
Is it possible to migrate the tables and its data when deploying to Azure?
If so, what would be the correct steps to do that?
Thanks in advance.
You can migrate tables. To migrate data, you should use Seed method of entity framework.
public class SchoolDBInitializer : DropCreateDatabaseAlways<SchoolDBContext>
{
protected override void Seed(SchoolDBContext context)
{
IList<Standard> defaultStandards = new List<Standard>();
defaultStandards.Add(new Standard() { StandardName = "Standard 1", Description = "First Standard" });
defaultStandards.Add(new Standard() { StandardName = "Standard 2", Description = "Second Standard" });
defaultStandards.Add(new Standard() { StandardName = "Standard 3", Description = "Third Standard" });
foreach (Standard std in defaultStandards)
context.Standards.Add(std);
base.Seed(context);
}
}
http://www.entityframeworktutorial.net/code-first/seed-database-in-code-first.aspx
In my opinion the best you can do, use Sql Server Data Tools. It will help you with tables and also data, because it uses a declarative mode. You 'declare' how should be your database, and it handles de updates.
https://www.youtube.com/watch?v=uPll3dMxTXU
I am using Fluent Migrator for keeping the database updated. The Up and Down functions works perfectly. Next step is that I want views to be created. These I would like to run from an .SQL file which i have. I want this to be run after all migrations has been run, everytime.
What i have currently is:
var blah = new MigrationConventions();
var maintenanceLoader = new MaintenanceLoader(_migrate, blah);
maintenanceLoader.ApplyMaintenance(MigrationStage.AfterAll);
and a class
[Maintenance(MigrationStage.AfterAll)]
public class ViewMaintenance
{
public ViewMaintenance() {
var blah = 123;
}
}
This is not fired because in maintenanceLoader there are 0 elements that it can find. I am inserting the _migrate, which is defined like this:
var runnerContext = new RunnerContext(new TextWriterAnnouncer(UpdateText));
_migrate = new MigrationRunner(
Assembly.GetExecutingAssembly(),
runnerContext,
new SqlServerProcessor(
new SqlConnection(connectionString),
new SqlServer2012Generator(),
new TextWriterAnnouncer(UpdateText),
new ProcessorOptions(),
new SqlServerDbFactory()));
Why can't the Assembly.GetExecutingAssembly() be scanned, and find the [Maintenance(MigrationStage.AfterAll)] be found?
I would also like for the ViewMaintenance class to be able to run the Execute.Sql( that the Migration classes has.
I downloaded the source code and figured it out.
In the class I want the maintenance to be run, I need to inherit from the : Migration class, just like with migrations (duh..). It will then have access to everything it has access to in migrations, including Execute.Sql(.
When it is inherited from, the Reflection in Fluent Migrator will search for it, find it, and use the attribute that is set to run it after all migrations is run.
This part is not needed:
var blah = new MigrationConventions();
var maintenanceLoader = new MaintenanceLoader(_migrate, blah);
maintenanceLoader.ApplyMaintenance(MigrationStage.AfterAll);
Neat :)
The following code does not work, and I can't explain why... My user manager is causing significant distress in that it creates users and roles just fine but when I run this code userManager.IsInRole is always returning false, so the second time I run my seed I am hitting errors because it is trying to create the record despite the fact it already exists!
Please note that this is occurring when I am running update-database against my migrations project, is the fact this is a non ASP project causing issues, if so why? shouldn't an error be thrown.
This is the first project I have used Identity and although when it works it seems good, there is very little up to date good quality documentation available, so if anyone has any sources for this I would be grateful.
public void Run(BlogContext blogContext)
{
var userStore = new UserStore<User>((BlogContext) blogContext);
var userManager = new UserManager<User>(userStore);
var userRoles = new List<UserRole>()
{
new UserRole() {Username = "SysAdmin#test.com", Role = "SysAdmin"},
new UserRole() {Username = "testAdmin#test.com", Role = "Admin"},
new UserRole() {Username = "testAuthor#test.com", Role = "Author"}
};
foreach (var userRole in userRoles)
{
var userId = userManager.FindByName(userRole.Username).Id;
if (!userManager.IsInRole(userId, userRole.Role))
userManager.AddToRole(userId, userRole.Role);
}
blogContext.SaveChanges();
}
So I will answer this myself to save anyone the hours of pain I suffered because of this.
The reason for this occurring was that I had lazy loading disabled, I have enabled this to be on in my Migrations project like so.
protected override void Seed(BlogContext blogContext)
{
AutomaticMigrationsEnabled = true;
blogContext.Configuration.LazyLoadingEnabled = true;
//Add seed classes here!
}