Generating a database script from entity framework code-first model - entity-framework

I'm using entity framework with code-first (primarily because with RIA Services, you need to have some form of the code classes anyway for additional attributes).
I want to get a database generation script to easily update the visual studio database project. I don't want to use ef migrations, I prefer the database projects.
I can use something like
string sqlscript = (context as IObjectContextAdapter).ObjectContext.CreateDatabaseScript();
at runtime, but I want to have a convenient method to get the script without running the project in some way, and without using migrations.
Does anybody have any ideas?
I'm using ef4.1 and ef5 in different projects.
[EDIT: One way of answering this question would be a way to call above line from the package manager console.]

One way is using the Entity Framework Power Tools. They add a context menu entry for the file containing the DbContext class which generates a DDL file for the database.
Another way is using LinqPad. After opening the dll in LinqPad, one can execute the code snippet given in the question in a query:
(this as IObjectContextAdapter).ObjectContext.CreateDatabaseScript()
Both ways are slightly inconvenient though as they require third-party tools.

I have enabled migrations but I always do get the script at runtime without using the Package Manager Console to update the database as I have dynamic entities that can only be discovered at runtime depending on what references are included in the project.
The code to get the script looks like this:
var config = new DbMigrationsConfiguration<MyContext> { AutomaticMigrationsEnabled = true };
var migrator = new DbMigrator(config);
var scriptor = new MigratorScriptingDecorator(migrator);
string script = scriptor.ScriptUpdate(sourceMigration: null, targetMigration: null);

You can also generate custom queries using the `ObjectQuery class.
Here's an example:
var query = from emp in context.Employees
select emp;
var sqlScript = ((ObjectQuery)query).ToTraceString();

An approach you can consider is to use ef migrations to generate the script, then use MSBuild post build task to copy the script over to the database project at build time.

Related

Entity Framework Core 2.0 Dynamically Creating A Database

I am new to EF Core, and as I tried using it I found out that you need to add migrations for it to create a database from models. My question is, do we have another option aside from migrations to dynamically create the database on run time just like what it was in EF 6?
Thanks.
Until a seeding mechanism is provided in EF Core you can provide your own seeding mechanism.
In earlier phases of a project, when the database is not yet fixed, I don't care that data get lost. When I want to recreate the database dynamically I call the function below. By the setting of a parameter I determine if this "recreateDatabase"-function is called yes or no. The function is included in MyOwnDbContext class.
The seed function you need to write is very similar to the one you use in EF 6.
private static void recreateDatabase(YourOwnDbContext dbContext)
{
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();
seed(dbContext);
}

EF 6 Mix Mode Code First and DB First

Iam using EF 6 with database first .. and every time I update the scheme : all my editings to the edmx file (mainly for defining db built in functions) are lost .. but using code first I can add my dbmodelbuilder calls in a separate file with partial class .. and by that I can also use all the nuget packages that targets code first such as EntityFramework.Functions.
Thanks for helping
You can use Code First from database option when you are creating your ADO.net entity data model. This will give you the code first classes that you can edit.
After creating your model you would need to stick to using the code first model otherwise you will need to regenerate your code-first after every database change...
Download the EF tools here.

EF migrations - call custom sql that is included into separate folder

For now we have used only initial migration but now our team is planning to use EF update migrations.
My question is about custom SQL:
I see that I can add custom SQL into migration
I see I can add it using SQL ("Update bla bla")
Instead I would like to add all custom SQL into a separate folder. How to call custom SQL that is included in separate folders?
P.S. We use EF 6
This feature will be available in version 6.1.2, currently available as beta:
SqlFile and SqlResource methods on DbMigration allow you to run a SQL script stored as a file or embedded resource.
Currently you can use:
var sqlFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
#"Migrations\Custom.sql");
Sql(File.ReadAllText(sqlFile));
http://blogs.msdn.com/b/adonet/archive/2014/09/18/ef6-1-2-beta-1-available.aspx
https://entityframework.codeplex.com/workitem/561

How to create new base line / reset in EF code first?

So when prototyping an application using Entity Framework code first, I ended up with a lot of migrations.
I'm not interested in keeping all the classes that were generated, I want to say: ok, this is my base line for v1.
How can I reset EF Code first?
If you want to return the first migration in your database you needs just:
Update-Database –TargetMigration:"YourFirstMigrationName"
in your parkage manage console.
But it just return the version of your database, not your code first POCO classes. For control the version you need another tool, like the Team foundation or git.

Can't enable Migrations in Entity Framework 4.3

I have a class library with EF Code First. I just upgraded to EF 4.3 and now I want to enable migrations.
I type Enable-Migrations -ProjectName MyProjectName in the PM console but receive the following error
PM> Enable-Migrations -ProjectName MyProjectName
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at System.Data.Entity.Migrations.DbMigrationsConfiguration.GetSqlGenerator(String providerInvariantName)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.RunCore()
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
The given key was not present in the dictionary.
PM>
I cant figure out what dictionary that might be wrong.
My connection string looks like this:
<connectionStrings>
<add name="MySystem" connectionString="Data Source=MyServer\Instance;Initial Catalog=myDbName;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
Any idea about what might be wrong?
Just a note:
I use my class library in a console application with an exact copy of my app.config and there I can access my database perfectly well.
It turned out Anders Abel was right in the cause, but we found a much simpler solution.
According to the mvc-mini-profiler page there is a special package in Nuget called MiniProfiler.EF that does not requires any wrapper around the SqlConnection. We dropped our old mvc-mini-profiler and installed the MiniProfiler.EF. Then Enable-Migrations worked as expected.
EF Code First has an extensible provider model for Sql code generation. The documentation for DbMigrationsConfiguration.GetSqlGenerator says what it does:
Gets the SQL generator that is set to be used with a given database
provider.
The MvcMiniProfiler wraps itself around the DB provider to add profiling support. To EF it will look like you're using a MvcMiniProfiler DB and not a MSSQL DB. Unfortunately EF Code first doesn't know how to handle a MvcMiniProfiler DB.
A possible fix would be to add a SqlGenerator with the MvcMiniProfiler name that wraps the Sql Server generator.
Edit
Looks like it might be possible to just reregister the existing sql server generator for the mvc mini profiler name (if you figure out the name of it).
At http://romiller.com/2012/01/16/customizing-code-first-migrations-provider/ there is code snippet that shows how to register a provider:
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("System.Data.SqlClient",
new CustomMigrationsProviders.CustomSqlServerMigrationSqlGenerator());
}
This may be a related, but different problem, but since it was Anders' post here that lead me to the solution, I figured I post this solution here as well.
The Problem:
If MiniProfiler is initialized before our Entity Framework database initialization strategies execute, the initialization fails with an error about a missing migration table.
If the Entity Framework database initialization strategies execute first, access to entities fails with a type casting exception as the MiniProfiler DbConnection is tried to be forced into a SqlConnection variable (in an internal generic).
The Cause:
When MiniProfiler initializes, it uses reflection to retrieve a collection of database providers from a private static field in System.Data.Common.DbProviderFactories. It then rewrites this list with MiniProfiler shim providers to replace the native providers. This allows MiniProfiler to intercept any calls to the database silently.
When Entity Framework initializes, it starts to compile the data models and create cached initialized databases stored in System.Data.Entity.Internal.LazyInternalContext inside some private static fields. Once these are created, queries against the DbContext use the cached models and databases which are internally typed to use the providers that existed at initialization time.
When the Entity Framework database initialization strategy runs, it needs access to the bare, native Sql provider, not the MiniProfiler shim, in order to correctly generate the SQL to create tables. But once these calls to the native provider are made, the native provider is cached into LazyInternalContext and we can no longer inject the MiniProfiler shims without runtime failures.
My Solution:
Access the private collections inside System.Data.Entity.Internal.LazyInternalContext and clear out the cached compiled models and initialized databases.
If I perform this purge between the operation of the EF database initialization strategies and the initialization of MiniProfiler, the MiniProfiler shims can then be inserted without causing later runtime failures.
Code:
This code did the trick for me:
Type type = typeof(DbContext).Assembly.GetType("System.Data.Entity.Internal.LazyInternalContext");
object concurrentDictionary = (type.GetField("InitializedDatabases", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var initializedDatabaseCache = (IDictionary)concurrentDictionary;
if (initializedDatabaseCache != null) initializedDatabaseCache.Clear();
object concurrentDictionary2 = (type.GetField("CachedModels", BindingFlags.NonPublic | BindingFlags.Static)).GetValue(null);
var modelsCache = (IDictionary)concurrentDictionary2;
if (modelsCache != null) modelsCache.Clear();
Warning:
It appears that the names of the internal fields in LazyInternalContext change between versions of EF, so you may need to modify this code to work with the exact version of EF that you include in your project.