Given Scenratio:
We've built a web application using Asp.net MVC and Entity Framework Code First, which builds a database dynamically for each customer.
Given a connection string (connectionStr) and a certain Configuration, We've made Add Migrations [Name] in order to create an empty migration, which has an empty Up function. We did that on purpose.
We don't wanna use automatic migrations here - we want full control, so we have a program making the migrations using a DbMigrator Class.
Our goal is to run a manual Seed inside this Up function.
This is some of the code incharge of making the migration, which indeed works perfectly:
Dim myConfiguration As New SomeNamespace.Migrations.Config1.Configuration
myConfiguration.TargetDatabase = New Infrastructure.DbConnectionInfo(connectionStr, "System.Data.SqlClient")
Dim dbMig As New Entity.Migrations.DbMigrator(myConfiguration)
If dbMig.GetPendingMigrations.Count > 0 Then
dbMig.Update() ' This makes the Up function work - the problem is inside it.
End If
Problem:
The problem is that when the Up function of the Migration is run, we cannot get the database context. We need it in order to make a Seed.
We hope that there's a way to get the Configuration object (myConfiguration) used to initiate the DbMigration (dbMig) instance, or some other way, so we can get the database context (maybe getting the ConnectionString somehow).
Help getting access to one of configuration object / database context / ConnectionString - would be very appreciated.
I don't think so, because what Up method does is filling Operations collection, and DbMigrator class actually executes these operations. So there is no 'context' when up is called.
What you can do is get connection string via ConfigurationManager class directly
Related
I have an MVC web application with code-first Entity Framework. We install this application in various computers as a local application. I made a migration to upgrade the database (in this case I added a new table), and after running the migration on upgrade, I want to insert initial data to the database so the users will be able to add/edit/delete them but I don't want the table to be empty at the first time.
Is there a way to do it automatically on upgrade without running a SQL script manually?
Migration class has up method,you can override it and insert/update records using SQL :
public override void Up() {
AddColumn("dbo.Posts", "Abstract", c => c.String());
Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
}
(Source)
Yes there is. You essentially write a class to conditionally check and insert values, and then you link this class to your entity framework database initialiser. It runs each time there is a migration to be performed, but I think you can change exactly when it runs (e.g. Application startup).
This link will give you the rough idea:
Entity Framework Inserting Initial Data On Rebuild
I have an exact code sample on my PC but I won't be on it until tomorrow. If this link doesn't quite do what you want, I can send you some code tomorrow which definitely will.
Is there a way for code in my ASP.NET MVC 4, code-first EF app to retrieve the current migration name? I want to display the migration name on an administrator's status page just as a sanity check to verify that the expected migration(s) have been applied.
You can use the DbMigrator (DbMigrator) class for that.
e.g.
var migrator = new DbMigrator(_configuration);
var pending = migrator.GetPendingMigrations();
var all = migrator.GetLocalMigrations();
Where _configuration is your Configuration class under the Migraiton dir.
You need to experiment a bit - see which actually fits your bill.
Also, I'm suggesting that you make an 'initializer' instead of just
adding that into the code. As that's how it's usually done, and a
'natural spot' for those things to happen (you don't 'call it', it
'calls you').
Check this link for an implementation of a custom initializer - which includes some DbMigrator code.
How to create initializer to create and migrate mysql database?
I have two databases that I am accessing. The first is against a contact database which I connected to using EF Model First; creating the edmx. I have since begun to learn the virtue of CODE First when working with Entity Framework, so I decided I would, in the same project, write the Product database using Code First techniques, allowing the database to be generated from the code I am writing.
Everything compiles fine. The problem occurs when I hit my harness and it attempts to create the Product database and retreive a list of values from one of the tables...
I get the folowing error "Could not find the conceptual model type for 'Core.Data.Account'", when I attempt to enumerate the ProductLines property (Line3 below).
1. using (var ctx = new ProductDb())
2. {
3. var lines = ctx.ProductLines.ToList();
4. this.litOne.Text = lines.Count.ToString();
5. }
After some research it appears that this message may be occuring because of multiple entities with the same name (regardless of namespace), however there is nothing in the ProductDb context with the name "Account".
There is a class in the OTHER context created by the Model First approach named "Account". But how/why would that make a difference? They each point to different databases i.e. different connection strings. Why would the ProductDb be attempting to create a table called Account, when it should be completely unaware of it's exstence?
thoughts?
Thank you as always!,
- G
I bumped into the same problem, but the other way around: first a DbContext + generated database and then generated an edmx off the database (just for a little presentation). It appeared to be a restriction in EF: EF currently has a restriction that POCO classes can't be loaded from an assembly that contains classes with the EF attributes.
The only thing you can do for now is keep the contexts in separate assemblies.
My application is using EF code-first design and all generally works very well.
Via a private configuration file, I can specify how I would like EF to handle changes to the db schema, and so create/recreate the relevant tables as desired - the options are "never" "create", "always", "onSchemaChanged" and (for the future) "onSchemaModified".
This works well - but I am getting lost in a couple of places .....
During development, I would like to use the hook as described in
"Database in use error with Entity Framework 4 Code First" - but this seems to execute on EVERY run of my program"
public void InitializeDatabase(Context context)
{
context.Database.SqlCommand("ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context); // Maybe this does nothing if not needed
context.Database.SqlCommand("ALTER DATABASE Tocrates SET MULTI_USER")
}
So .. to real my question: Is there an override that I can use to detect whether EF will ACTUALLY be trying to modify the database, so I can set this SINGLE_USER stuff when needed? And if so, can I detect the reason EF it is doing so (see my list of options above) so I can log the reason for change?...
All help and suggestions are very much appreciated.
Unless you have set the database intializer to null initializers run always once (per application lifetime) when you are using a context for the first time. What then actually happens depends on the initializer (your inner _intializer):
For DropCreateDatabaseAlways and CreateDatabaseIfNotExists it's clear by their name what they do.
For DropCreateDatabaseIfModelChanges there is only the question if the model changed or not. EF detects this by comparing a model hash with a hash stored in the database. You can check this yourself by calling...
bool compatible = context.Database.CompatibleWithModel(true);
...within your custom InitializeDatabase and then decide based on the result if you want to send your SqlCommands or not. (Don't call this with a self-created context because it will cause the database to be intialized first before the model compatibilty is checked.) The parameter bool throwIfNoMetadata (which is true in my example) causes EF to throw an exception if the model hash in the database does not exist. Otherwise the method will return true in that case.
For a custom inner initializer: Whatever your code will do.
Is there a way when i add a new entity to my Code First configuration the table gets automatically added so i don't have to worry about updating my DB with new tables?
you can add
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<YourDbContext>());
in you r application start . It will recreate database for you if you have modified your configuration.
And if you do not want to drop and create database (To incremental development) you can use SqlMigrations. http://www.hanselman.com/blog/EntityFrameworkCodeFirstMigrationsAlphaNuGetPackageOfTheWeek10.aspx
From: http://blogs.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-code-first-walkthrough.aspx
Setting an Initialization Strategy
In the next section we are going to start changing our model which in turn means the database schema needs to change as well. Currently there is no ‘out of the box’ solution to evolve your existing schema in place. Database evolution is something we are currently working on and a sample of the direction we are heading is provided in a recent design blog post.
There is however the opportunity to run some custom logic to initialize the database the first time a context is used in an AppDomain. This is handy if you want to insert seed data for test runs but it’s also useful to re-create the database if the model has changed. In CTP5 we include a couple of strategies you can plug in but you can also write custom ones.
Add a using statement for System.Data.Entity.Database at the top of Program.cs
using System.Data.Entity.Database;
For the walkthrough we just want to drop and re-create the database whenever the model has changed, so at the top of the Main method in my Program class I’ve added the following code
DbDatabase.SetInitializer<ProductContext>(
new DropCreateDatabaseIfModelChanges<ProductContext>());