How can I seed data to already created database? - c#

I am creating a football manager game. I have used identity 2.0 as it will work well for my registration and login. I was able to add the extra tables that were needed but now I need to seed the data such as teams and players to these table. Any idea how to do so? The extra tables were created in the identity models using migrations. Here is a picture of the tables I am using.

In the Migrations folder, there is a file called Configuration.cs with the Seed method that you can use to create some seed data.
protected override void Seed(ApplicationDbContext 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.
//add roles
context.Roles.AddOrUpdate(p => p.Id,
new IdentityRole()
{
Id = EnumUtility<AspNetRoles>.GetAppRoleId(AspNetRoles.None),
Name = AspNetRoles.None.ToString()
});
}
Just run update-database and you should have data in your tables.

There are 2 Seed() methods available - one in certain initializers such as CreateDatabaseIfNotExist that is run whenever the database is created. The other is the migration Seed() which runs whenever you apply a migration via update-database.
Since it runs with every migration, you want to make sure you don't duplicate your data. You could do this by checking for existence:
if (!context.Teams.Any())
{
context.Teams.Add(new Team { Name = "Team A" });
context.Teams.Add(new Team { Name = "Team B" });
}
But there is a better way designed specifically for migrations called AddOrUpdate:
protected override void Seed(ApplicationDbContext context)
{
context.Teams.AddOrUpdate(
team => team.Id, // put the key or unique field here
new Team
{
Id = 1,
Name = "Team 1"
},
new Team
{
Id = 2,
Name = "Team 2"
});
context.SaveChanges();
}

Related

How access to my old tables with different schema?

I had one DbContext with name AppDbContext in my .net core library.Now I decided to rename the current AppDbContet to PoemDBContext and change schema from dbo to Poems,And then I added another Library to this project that had Same Context Name As Old Context(AppDbContext), So my mistake was not to do these things step by step, So EF didn't make the right diagnosis in the changes I made to the project.Then I added a migration and update database.Now I have two version of tables For example I have
dbo.Poems
Poems.Poems
So I have run the project with no error But It didn't show the Poems ,Because new tables with Poems schema are empty.Now How can I access to my old table to copy them in my new tables?
[HttpGet("RandomPoem")]
public async Task<IActionResult> RandomPoem()
{
int PoemNumber = jrng.GetInt(1, 459);//Get Random Number
Poem UserPoem = db.Poems.Where(e => e.Number == PoemNumber).Include(e=>e.Hemistichs).FirstOrDefault();
if (UserPoem ==null)
{
return BadRequest("Poem Not Found!");
}
return Ok((PoemModel)UserPoem);
}
How can I access to dbo.Poems table in ef core?
You need two DbContext and when you configure it you can choose schema.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("Poems");
base.OnModelCreating(modelBuilder);
}

Previously no-tracking entities get tracked upon calling Savechages(). Is this normal?

I have a simple controller in which I create and add a user and a profile to the database
public async ActionResult AddUserAndProfile(string id)
{
_context.Users.Add(new User { Id = id });
_context.SaveChanges(); // If this line is removed, error doesn't occur.
var profile = new Profile
{
Id = "id",
User = _context.Users.AsNoTracking().FirstOrDefault(u => u.Id.Equals(id))
}; // Exception given on this line.
_context.Profiles.Add(profile);
_context.SaveChanges();
return Ok();
}
When I call this controller with id = "0" I get the following exception:
The instance of entity type 'User' cannot be tracked because another instance with the key value '{Id: 0}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
However, if I remove the first SaveChanges() call, this error is not shown.
1st question: Is it intended that entities get tracked after saving changes, wouldn't it make sense that they get tracked beforehand only? Also afaik, add actions don't mark entities as tracked.
2nd question: When is the best time to call SaveChages() in this situation? (It is important to note that add user and add profile actions are in different repo methods in the real project. I simplified the code here.)
3rd question: What is the best way to add foreign keys in situations like this?
You should be able to save whole hierarchy within one call to SaveChanges:
var profile = new Profile
{
Id = "id",
User = new User { Id = id }
};
_context.Profiles.Add(profile);
_context.SaveChanges();
It should answer 2nd and 3rd questions I think. As for the first one - there is a github issue with request to "Do not track after SaveChanges()".
Since you have different methods you can just set the UserId property on Profile (if you have explicitly added it to Profile entity) directly.
Save the user you create, and then specify that user for the profile.
var user = new User { Id = id };
_context.Users.Add(user);
_context.SaveChanges();
var profile = new Profile {Id = "id", User = user};

EF move migration to new project

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" }
// );
//
}
}

code first migration not working when deploying to Azure

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

Entity Framework Code First: Configuration.cs seed or custom initializer

I am working with the the Code First style of the Entity Framework for my first time. I want to set up some default data. The first approach I came across involved creating a custom initializer. I was headed this route but noticed after setting up migrations that it came with the Configuration.cs that already overrides the seed method just like the custom initializer.
internal sealed class Configuration : DbMigrationsConfiguration<Toolkit.Model.ToolkitContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(Toolkit.Model.ToolkitContext 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" }
// );
//
}
}
So it seems there are two ways to accomplish this task. Can someone shed some light on what would be the recommended way of doing this? Or does it matter at all and I should just flip a coin?
The Configuration.cs Seed method will run every time your model changes to make sure that some specific data stays in your DB, or to even possibly to reset that data to a specified default setting.
The Custom Initializer's seed method, on the other hand, can be setup to run every single time the application loads, like in this code, which is currently in the Global.asax file of my MVC page:
Database.SetInitializer(new MyCustomInitializer<MyDbContext, Configuration>());
var db = new MyDbContext();
db.Database.Initialize(true);
The practical difference really comes into play after you deploy your application. The Custom Initializer will make sure that no user can destroy some data that's absolutely required in your program.

Categories

Resources