Entity Framework: Only Seed when building initial database - c#

I'm using Entity Framework 6 with this DbMigrationsConfiguration:
public sealed class Configuration : DbMigrationsConfiguration<DataContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(Danfoss.EnergyEfficiency.Data.DataContext context)
{
//Adding initial data to context
context.SaveChanges();
}
}
I'm using it in WebAPI in this way:
public static void Register(HttpConfiguration config)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<DataContext, Configuration>());
}
I have noticed that Seed function is running every time my application start up. How can I prevent this? I only like it to run the first time it runs, when it build the initial tables.

The DbMigrationsConfiguration.Seed method is called every time you call Update-Database. The reasoning behind that is explained in this blog by One Unicorn.
That means that you have to write your Seed code to cope with existing data. If you don't like that, you can vote for a change on CodePlex.
In the meantime, to quote the blog:
The best way to handle this is usually to not use AddOrUpdate for
every entity, but to instead be more intentional about checking the
database for existing data using any mechanisms that are appropriate.
For example, Seed might check whether or not one representative entity
exists and then branch on that result to either update everything or
insert everything
Another option, that I have used in the past, is to add standing data that is related to a migration in the migration itself, using the Sql command. That way it only runs once. I have tended to move away from this because I prefer to keep the seeding in one place.

I've had the same issue in that I wanted an initial user created on database build. What I did was to create a blank migration and then add in the user creation there. Since a migration technically runs only once unless you remove and reapply migrations, this would ensure it would only run once on database creation.
I know that this question is a bit old, so it may help others or you may not be using migrations. But if you are, this is a handy technique.

Related

How can I run SQL script in OnModelCreating by EF Core?

My program has an existing SQLite database.
In the new version of the program, it needs to add a column for a feature.
Now the program is made by .NET 6 (WPF) and EF Core 6.
I have to detect whether the new column existed and add it or not.
Here is my code in OnModelCreating to detect the column existed or not:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
var Result = Database.ExecuteSqlRaw("SELECT Count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='BindDesign' AND COLUMN_NAME='type'");
}
After the code run, it reports this error:
An attempt was made to use the model while it was being created. A DbContext instance cannot be used inside 'OnModelCreating' in any way that makes use of the model that is being created
How can I solve this? Thank you.
You should use migrations to add columns in the database.
If you want to apply migrations on startup you can check if the database needs to be migrated and apply the migration with something like this
if (_context.Database.GetPendingMigrations().Any()) {
await _context.Database.MigrateAsync();
}
Try to Use Different Context for your schema , the error message is clear , you can on use makes use of the model that is being created.
just make another context for your schema .

Ensure database has been updated before returning with Entity Framework and C#

I have a situation where I am caching the contents of a table in the database. I am using Entity Framework 6 against an SQL Azure back-end. When the data in the table is updated.The process looks a little like this:
Receive data from UI
Insert/Update according to current state of store
Trigger Cache rebuild ( on separate service )
Then on the cache service
Clear cache
Load all entities from the table
Add the collection to the cache
The code on the data service works along these lines- this is obviously a highly abstracted version, but it shows the steps we go through:
public void UpdateProperty( int newVal )
{
SetNewPropertyVal(newVal);
TriggerUpdateEvent( newVal );
}
private void SetNewPropertyVal(int newVal)
{
using (var context = new MyContext())
{
using ( var mySet = context.Set<MyEntityType>();
{
var record = mySet.FindRecordToUpdate();
record.UpdateableFieldValue = newVal;
context.SaveChanges();
}
}
}
The problem is that although context.SaveChanges() has been called before the TriggerUpdateEvent is raised, when cache rebuild ( running in a separate, fully independent, thread against a separate instance of the DbContext ) retrieves the collection of entities, it contains the old value for the updated property. This looks like a race condition- if I put a simple Thread.Sleep(1000) in the cache refresh it works consistently, but I can't believe that is a good solution to this problem.
How do I avoid triggering a cache rebuild until the Entity Framework has actually updated the data store? I thought a transaction might do the trick, but SQL Azure doesn't seem to offer them.
In this case #ivan-stoev correctly explained that there is no reason for this code to fail synchronously. That lead me to explore the Cache rebuild process in more detail and there was a reliance on a second cache concealed away in an AutoMapper configuration that was causing the old value to show up in my searches.
So for anyone else who turns up with this problem, the bug isn't in this part of your code.

Entity Framework 7 - run seed at the end of the migration [duplicate]

This question already has answers here:
How to seed in Entity Framework Core 2?
(9 answers)
Closed 4 years ago.
I have a migration class:
public partial class TestMigration : Migration
{
protected override void Up(MigrationBuilder db)
{
At the end of the Up method, I would like to add some data (seed). MigrationBuilder exposes some methods, also Sql(), but I would like to use EF.
Can I inject DbContext here and do some stuff?
I do not recommended you to seed the database in the Migration up or down. this is a bad practice.
You can execute Sql statement in your up/down method and seed the tables as following:
EF6:
public override void Up()
{
Sql("INSERT INTO Customers (CustomerName, ContactName) VALUES ('Cardinal','Tom B.')");
...
}
EF Core 1.0 /7:
protected override void Up(MigrationBuilder db)
{
db.Sql("INSERT INTO Customers (CustomerName, ContactName) VALUES ('Cardinal','Tom B.')");
}
where Customer is an entity of the DbSet<'Customer'> Customers by your DbContext
You can create you DbContext during the migration by suppling the connection string or load it from the confiugration but think good about that the database at this time point is not completed and the updating progress still in use. this thing might make for you later really a big troubles.
1) Use the normal DBInitializer.Seed to seed the data to the database.
2) Use the Sql statements in your Migrations Up/Down to transform(update/delete/insert) the data and make the data compatibility between the old database schema and the new one during the migration.
3) Do not try to create DbContext wthing the migration process.
It’s not possible to modify the data during migrations. The current solution for seeding databases is to do that when the application launches, as shown in the Unicode Store sample which ensures that all seed data is available.
There was a discussions on this in issue 3042, the current effort seems to be to change the migration story to make it possible to seed data during a migration. It’s currently planned post-RTM though, so I wouldn’t bet on that for now.

EF Migrations for Database-first approach?

We're using Database first approach with EntityFramework.
We've several customers, and when we deploy new product version, we're now applying DB schema changes "manually" with tools like SQL Compare.
Is there a way how EF Migrations could help to apply changes to customers DB automatically?
As far as I know, EF Migrations is a product targeted at CodeFirst and doesn't support Database First operations.
CodeFirst assumes that you will never make any changes manually to the database. All the changes to the database will go through the code first migrations.
I think there is! You need to continue your way through the code first.
To do this, Suppose that you have the following DbContext that EF Db first created for you:
public class MyDbContext : DbContext
{
public MyDbContext()
: base("Name=DefaultConnection")
{
}
// DbSets ...
}
change that to the following to start using code first and all magic tools of it (migration, etc.):
public class MyDbContext : DbContext
{
public MyDbContext()
: base("YourDbFileName")
{
}
// DbSets ...
}
It causes that EF creates a new connection string using SQL Express on your local machine in your web.config file with the name YourDbFileName, something just like the early DefaultConnection Db first created.
All you may need to continue your way, is that edit the YourDbFileName ConStr according to your server and other options.
More info here and here.
Starting Entity Framework 4.1 you can do Code First Migrations with an existing database.
So first you have the database, create the model, enable migrations.
The most important thing to remember that you should run Enable-Migrations before you do any changes to the schema since it should be in sync between your db and code.
Just look for your DbContext child object and look for this method:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
If you comment this:
throw new UnintentionalCodeFirstException();
then the exception would not be thrown on migration operation. As you might imagine, the migration look for this part to know what are the configurations for each entity with what table or tables.
Sorry if I didn't go with more details, if you wish more, I'll be happy to edit this and make it better!

About Code First Database Evolution (aka Migrations)

I watched a screencast from MSDN BLOG that talks about database migration.
Is there anyone who knows when can we use this feature? It looks it doesn't work in CTP5 yet.
By the way, is there any way to seed the initial data after I changed the schema code?
This is what am I doing right now, it wipes all the data every time I altered the model.
DbDatabase.SetInitializer<Context>(
new DropCreateDatabaseIfModelChanges<Context>());
They most likely get this migration feature in the RTM version which is targeted for the first quarter of 2011.
To populate database with some initial data you can create your own database initializer and have it inherit from your desired strategy (right now we have 2 options) and then override Seed method inside it:
public class MyInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{
protected override void Seed(InheritanceMappingContext context)
{
MyEntity entity = new MyEntity()
{
...
};
context.MyEntities.Add(entity);
context.SaveChanges();
}
}
Alpha 3 is out now.
http://blogs.msdn.com/b/adonet/archive/2011/09/21/code-first-migrations-alpha-3-no-magic-walkthrough.aspx
EF 4.1 Candidate Release has been issued in March and looks like this Migration feature is not yet included

Categories